427664f5eygrc3nEhI3RKf0Y37PzyA xen/arch/ia64/xentime.c
3ddb79bcZbRBzT3elFWSX7u6NtMagQ xen/arch/x86/Makefile
3ddb79bcBQF85CfLS4i1WGZ4oLLaCA xen/arch/x86/Rules.mk
-3e5636e5FAYZ5_vQnmgwFJfSdmO5Mw xen/arch/x86/acpi.c
+3e5636e5FAYZ5_vQnmgwFJfSdmO5Mw xen/arch/x86/acpi/boot.c
3ddb79bcsjinG9k1KcvbVBuas1R2dA xen/arch/x86/apic.c
42360b3244-Q6BpEKhR_A1YtG1wPNQ xen/arch/x86/audit.c
3ddb79c4yGZ7_22QAFFwPzqP4NSHwA xen/arch/x86/boot/mkelf32.c
422f27c8J9DQfCpegccMid59XhSmGA xen/arch/x86/x86_emulate.c
3ddb79bdff-gj-jFGKjOejeHLqL8Lg xen/common/Makefile
3e397e66AyyD5fYraAySWuwi9uqSXg xen/common/ac_timer.c
+427fa2d0J0LU2s5oKbsM0nTZ2iyd2Q xen/common/bitmap.c
3ddb79bdLX_P6iB7ILiblRLWvebapg xen/common/dom0_ops.c
3e6377e4i0c9GtKN65e99OtRbw3AZw xen/common/dom_mem_ops.c
3ddb79bdYO5D8Av12NHqPeSviav7cg xen/common/domain.c
4204e7acwXDo-5iAAiO2eQbtDeYZXA xen/include/asm-x86/init.h
3ddb79c3fQ_O3o5NHK2N8AJdk0Ea4Q xen/include/asm-x86/io.h
3ddb79c2TKeScYHQZreTdHqYNLbehQ xen/include/asm-x86/io_apic.h
-42605109qxLSrHVE2SRhGXmgk907iw xen/include/asm-x86/io_ports.h
3ddb79c2L7rTlFzazOLW1XuSZefpFw xen/include/asm-x86/irq.h
404f1b93OjLO4bFfBXYNaJdIqlNz-Q xen/include/asm-x86/ldt.h
-4260510aYPj2kr6rMbBfMxcvvmXndQ xen/include/asm-x86/mach_apic.h
+427fa2d0m8MOSSXT13zgb-q0fGA_Dw xen/include/asm-x86/mach-default/apm.h
+427fa2d0suK9Av7vsAXhsQxZjqpc_Q xen/include/asm-x86/mach-default/bios_ebda.h
+427fa2d0yC3KzLozoeK3Xa3uGVfIdw xen/include/asm-x86/mach-default/do_timer.h
+427fa2d0bWQkR1mW5OBYxn07AN-bDw xen/include/asm-x86/mach-default/entry_arch.h
+427fa2d0-SWcuwbdSypo4953bc2JdQ xen/include/asm-x86/mach-default/io_ports.h
+427fa2d0eyAl7LAeO-SVV4IW7lZPGQ xen/include/asm-x86/mach-default/irq_vectors.h
+427fa2d0df7VWG4KKpnKbKR2Cbd1_w xen/include/asm-x86/mach-default/irq_vectors_limits.h
+4260510aYPj2kr6rMbBfMxcvvmXndQ xen/include/asm-x86/mach-default/mach_apic.h
+427fa2d0I3FWjE2tWdOhlEOJn7stcg xen/include/asm-x86/mach-default/mach_apicdef.h
+427fa2d093fDS2gOBLcl7Yndzl7HmA xen/include/asm-x86/mach-default/mach_ipi.h
+427fa2d0Y7bD35d-FvDAeiJDIdRw2A xen/include/asm-x86/mach-default/mach_mpparse.h
+427fa2d0aLQgE9e1GY9ZP5jrMOC8pQ xen/include/asm-x86/mach-default/mach_mpspec.h
+427fa2d0fJ5nNn5ydJuOaZIL6F2fjQ xen/include/asm-x86/mach-default/mach_reboot.h
+427fa2d0VlN555TE68TjKMsrOoFXNA xen/include/asm-x86/mach-default/mach_time.h
+427fa2d0C0jWTKYjy7WJjGKeujSpSg xen/include/asm-x86/mach-default/mach_timer.h
+427fa2d0UXLiS1scpNrK26ZT6Oes3g xen/include/asm-x86/mach-default/mach_traps.h
+427fa2d0OfglYyfpDTD5DII4M0uZRw xen/include/asm-x86/mach-default/mach_wakecpu.h
+427fa2d0_OBPxdi5Qo04JWgZhz7BFA xen/include/asm-x86/mach-default/pci-functions.h
+427fa2d0mrTtXrliqDfLuJc5LLVXaA xen/include/asm-x86/mach-default/setup_arch_post.h
+427fa2d0Uoo7gC61Kep6Yy7Os367Hg xen/include/asm-x86/mach-default/setup_arch_pre.h
+427fa2d1EKnA8zCq2QLHiGOUqOgszg xen/include/asm-x86/mach-default/smpboot_hooks.h
3ddb79c3I98vWcQR8xEo34JMJ4Ahyw xen/include/asm-x86/mc146818rtc.h
40ec25fd7cSvbP7Biw91zaU_g0xsEQ xen/include/asm-x86/mm.h
3ddb79c3n_UbPuxlkNxvvLycClIkxA xen/include/asm-x86/mpspec.h
+427fa2d1eJRenftJJnRyLsHKl1ghtA xen/include/asm-x86/mpspec_def.h
3ddb79c2wa0dA_LGigxOelSGbJ284Q xen/include/asm-x86/msr.h
41aaf567Mi3OishhvrCtET1y-mxQBg xen/include/asm-x86/mtrr.h
41a61536MFhNalgbVmYGXAhQsPTZNw xen/include/asm-x86/multicall.h
3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/public/xen.h
3e397e66m2tO3s-J8Jnr7Ws_tGoPTg xen/include/xen/ac_timer.h
40715b2epYl2jBbxzz9CI2rgIca7Zg xen/include/xen/acpi.h
+427fa2d1wyoVbvCyZRLposYjA_D_4g xen/include/xen/bitmap.h
+427fa2d1ItcC_yWuBUkhc7adedP5ow xen/include/xen/bitops.h
3ddb79c0c0cX_DZE209-Bb-Rx1v-Aw xen/include/xen/cache.h
41f2cea7Yna7xc0X9fyavIjoSFFeVg xen/include/xen/compile.h.in
3f840f12CkbYSlwMrY2S11Mpyxg7Nw xen/include/xen/compiler.h
3ddb79c259jh8hE7vre_8NuE7nwNSA xen/include/xen/config.h
3eb165e0eawr3R-p2ZQtSdLWtLRN_A xen/include/xen/console.h
+427fa2d1bQCWgEQqTTh5MjG4MPEH9g xen/include/xen/cpumask.h
3ddb79c1V44RD26YqCUm-kqIupM37A xen/include/xen/ctype.h
3ddb79c05DdHQ0UxX_jKsXdR4QlMCA xen/include/xen/delay.h
40f2b4a2hC3HtChu-ArD8LyojxWMjg xen/include/xen/domain.h
OBJS += $(patsubst %.S,%.o,$(wildcard $(TARGET_SUBARCH)/*.S))
OBJS += $(patsubst %.c,%.o,$(wildcard $(TARGET_SUBARCH)/*.c))
+OBJS += $(patsubst %.c,%.o,$(wildcard acpi/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard mtrr/*.c))
OBJS := $(subst $(TARGET_SUBARCH)/asm-offsets.o,,$(OBJS))
# x86-specific definitions
CFLAGS += -nostdinc -fno-builtin -fno-common -fno-strict-aliasing
-CFLAGS += -iwithprefix include -Wall -Werror -pipe
-CFLAGS += -I$(BASEDIR)/include -Wno-pointer-arith -Wredundant-decls
+CFLAGS += -iwithprefix include -Wall -Werror -Wno-pointer-arith -pipe
+CFLAGS += -I$(BASEDIR)/include -I$(BASEDIR)/include/asm-x86/mach-default
ifeq ($(optimize),y)
CFLAGS += -O3 -fomit-frame-pointer
+++ /dev/null
-/*
- * acpi.c - Architecture-Specific Low-Level ACPI Support
- *
- * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
- * Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
- * Copyright (C) 2001 Patrick Mochel <mochel@osdl.org>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-#include <xen/config.h>
-#include <xen/kernel.h>
-#include <xen/init.h>
-#include <xen/types.h>
-#include <xen/slab.h>
-#include <xen/pci.h>
-#include <xen/irq.h>
-#include <xen/acpi.h>
-#include <asm/mpspec.h>
-#include <asm/io.h>
-#include <asm/apic.h>
-#include <asm/apicdef.h>
-#include <asm/page.h>
-#include <asm/io_apic.h>
-#include <asm/acpi.h>
-#include <asm/smpboot.h>
-
-
-#define PREFIX "ACPI: "
-
-int acpi_lapic;
-int acpi_ioapic;
-int acpi_strict;
-
-acpi_interrupt_flags acpi_sci_flags __initdata;
-int acpi_sci_override_gsi __initdata;
-/* --------------------------------------------------------------------------
- Boot-time Configuration
- -------------------------------------------------------------------------- */
-
-int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */
-int acpi_ht __initdata = 1; /* enable HT */
-
-enum acpi_irq_model_id acpi_irq_model;
-
-
-/*
- * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
- * to map the target physical address. The problem is that set_fixmap()
- * provides a single page, and it is possible that the page is not
- * sufficient.
- * By using this area, we can map up to MAX_IO_APICS pages temporarily,
- * i.e. until the next __va_range() call.
- *
- * Important Safety Note: The fixed I/O APIC page numbers are *subtracted*
- * from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and
- * count idx down while incrementing the phys address.
- */
-char *__acpi_map_table(unsigned long phys, unsigned long size)
-{
- unsigned long base, offset, mapped_size;
- int idx;
-
- if (phys + size < 8*1024*1024)
- return __va(phys);
-
- offset = phys & (PAGE_SIZE - 1);
- mapped_size = PAGE_SIZE - offset;
- set_fixmap(FIX_ACPI_END, phys);
- base = fix_to_virt(FIX_ACPI_END);
-
- /*
- * Most cases can be covered by the below.
- */
- idx = FIX_ACPI_END;
- while (mapped_size < size) {
- if (--idx < FIX_ACPI_BEGIN)
- return 0; /* cannot handle this */
- phys += PAGE_SIZE;
- set_fixmap(idx, phys);
- mapped_size += PAGE_SIZE;
- }
-
- return ((char *) base + offset);
-}
-
-
-#ifdef CONFIG_X86_LOCAL_APIC
-
-static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
-
-
-static int __init
-acpi_parse_madt (
- unsigned long phys_addr,
- unsigned long size)
-{
- struct acpi_table_madt *madt = NULL;
-
- if (!phys_addr || !size)
- return -EINVAL;
-
- madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size);
- if (!madt) {
- printk(KERN_WARNING PREFIX "Unable to map MADT\n");
- return -ENODEV;
- }
-
- if (madt->lapic_address)
- acpi_lapic_addr = (u64) madt->lapic_address;
-
- printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n",
- madt->lapic_address);
-
- detect_clustered_apic(madt->header.oem_id, madt->header.oem_table_id);
-
- return 0;
-}
-
-
-static int __init
-acpi_parse_lapic (
- acpi_table_entry_header *header)
-{
- struct acpi_table_lapic *processor = NULL;
-
- processor = (struct acpi_table_lapic*) header;
- if (!processor)
- return -EINVAL;
-
- acpi_table_print_madt_entry(header);
-
- mp_register_lapic (
- processor->id, /* APIC ID */
- processor->flags.enabled); /* Enabled? */
-
- return 0;
-}
-
-
-static int __init
-acpi_parse_lapic_addr_ovr (
- acpi_table_entry_header *header)
-{
- struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;
-
- lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
- if (!lapic_addr_ovr)
- return -EINVAL;
-
- acpi_lapic_addr = lapic_addr_ovr->address;
-
- return 0;
-}
-
-static int __init
-acpi_parse_lapic_nmi (
- acpi_table_entry_header *header)
-{
- struct acpi_table_lapic_nmi *lapic_nmi = NULL;
-
- lapic_nmi = (struct acpi_table_lapic_nmi*) header;
- if (!lapic_nmi)
- return -EINVAL;
-
- acpi_table_print_madt_entry(header);
-
- if (lapic_nmi->lint != 1)
- printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
-
- return 0;
-}
-
-#endif /*CONFIG_X86_LOCAL_APIC*/
-
-#if defined(CONFIG_X86_IO_APIC) /*&& defined(CONFIG_ACPI_INTERPRETER)*/
-
-static int __init
-acpi_parse_ioapic (
- acpi_table_entry_header *header)
-{
- struct acpi_table_ioapic *ioapic = NULL;
-
- ioapic = (struct acpi_table_ioapic*) header;
- if (!ioapic)
- return -EINVAL;
-
- acpi_table_print_madt_entry(header);
-
- mp_register_ioapic (
- ioapic->id,
- ioapic->address,
- ioapic->global_irq_base);
-
- return 0;
-}
-
-#ifdef CONFIG_ACPI_INTERPRETER
-/*
- * Parse Interrupt Source Override for the ACPI SCI
- */
-static void
-acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
-{
- if (trigger == 0) /* compatible SCI trigger is level */
- trigger = 3;
-
- if (polarity == 0) /* compatible SCI polarity is low */
- polarity = 3;
-
- /* Command-line over-ride via acpi_sci= */
- if (acpi_sci_flags.trigger)
- trigger = acpi_sci_flags.trigger;
-
- if (acpi_sci_flags.polarity)
- polarity = acpi_sci_flags.polarity;
-
- /*
- * mp_config_acpi_legacy_irqs() already setup IRQs < 16
- * If GSI is < 16, this will update its flags,
- * else it will create a new mp_irqs[] entry.
- */
- mp_override_legacy_irq(gsi, polarity, trigger, gsi);
-
- /*
- * stash over-ride to indicate we've been here
- * and for later update of acpi_fadt
- */
- acpi_sci_override_gsi = gsi;
- return;
-}
-#endif
-
-static int __init
-acpi_parse_fadt(unsigned long phys, unsigned long size)
-{
- struct fadt_descriptor_rev2 *fadt =0;
-
- fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size);
- if (!fadt) {
- printk(KERN_WARNING PREFIX "Unable to map FADT\n");
- return 0;
- }
-
-#ifdef CONFIG_ACPI_INTERPRETER
- /* initialize sci_int early for INT_SRC_OVR MADT parsing */
- acpi_fadt.sci_int = fadt->sci_int;
-#endif
-
- return 0;
-}
-
-
-static int __init
-acpi_parse_int_src_ovr (
- acpi_table_entry_header *header)
-{
- struct acpi_table_int_src_ovr *intsrc = NULL;
-
- intsrc = (struct acpi_table_int_src_ovr*) header;
- if (!intsrc)
- return -EINVAL;
-
- acpi_table_print_madt_entry(header);
-
-#ifdef CONFIG_ACPI_INTERPRETER
- if (intsrc->bus_irq == acpi_fadt.sci_int) {
- acpi_sci_ioapic_setup(intsrc->global_irq,
- intsrc->flags.polarity, intsrc->flags.trigger);
- return 0;
- }
-#endif
-
- mp_override_legacy_irq (
- intsrc->bus_irq,
- intsrc->flags.polarity,
- intsrc->flags.trigger,
- intsrc->global_irq);
-
- return 0;
-}
-
-
-static int __init
-acpi_parse_nmi_src (
- acpi_table_entry_header *header)
-{
- struct acpi_table_nmi_src *nmi_src = NULL;
-
- nmi_src = (struct acpi_table_nmi_src*) header;
- if (!nmi_src)
- return -EINVAL;
-
- acpi_table_print_madt_entry(header);
-
- /* TBD: Support nimsrc entries? */
-
- return 0;
-}
-
-#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
-
-
-static unsigned long __init
-acpi_scan_rsdp (
- unsigned long start,
- unsigned long length)
-{
- unsigned long offset = 0;
- unsigned long sig_len = sizeof("RSD PTR ") - 1;
-
- /*
- * Scan all 16-byte boundaries of the physical memory region for the
- * RSDP signature.
- */
- for (offset = 0; offset < length; offset += 16) {
- if (strncmp((char *) (start + offset), "RSD PTR ", sig_len))
- continue;
- return (start + offset);
- }
-
- return 0;
-}
-
-
-unsigned long __init
-acpi_find_rsdp (void)
-{
- unsigned long rsdp_phys = 0;
-
- /*
- * Scan memory looking for the RSDP signature. First search EBDA (low
- * memory) paragraphs and then search upper memory (E0000-FFFFF).
- */
- rsdp_phys = acpi_scan_rsdp (0, 0x400);
- if (!rsdp_phys)
- rsdp_phys = acpi_scan_rsdp (0xE0000, 0x20000);
-
- return rsdp_phys;
-}
-
-
-/*
- * acpi_boot_init()
- * called from setup_arch(), always.
- * 1. maps ACPI tables for later use
- * 2. enumerates lapics
- * 3. enumerates io-apics
- *
- * side effects:
- * acpi_lapic = 1 if LAPIC found
- * acpi_ioapic = 1 if IOAPIC found
- * if (acpi_lapic && acpi_ioapic) smp_found_config = 1;
- * if acpi_blacklisted() disable_acpi()
- * acpi_irq_model=...
- * ...
- *
- * return value: (currently ignored)
- * 0: success
- * !0: failure
- */
-int __init
-acpi_boot_init (void)
-{
- int result = 0;
-
- if (acpi_disabled && !acpi_ht)
- return(1);
-
- /*
- * The default interrupt routing model is PIC (8259). This gets
- * overriden if IOAPICs are enumerated (below).
- */
- acpi_irq_model = ACPI_IRQ_MODEL_PIC;
-
- /*
- * Initialize the ACPI boot-time table parser.
- */
- result = acpi_table_init();
- if (result) {
- disable_acpi();
- return result;
- }
-
- result = acpi_blacklisted();
- if (result) {
- printk(KERN_NOTICE PREFIX "BIOS listed in blacklist, disabling ACPI support\n");
- disable_acpi();
- return result;
- }
-
-#ifdef CONFIG_X86_LOCAL_APIC
-
- /*
- * MADT
- * ----
- * Parse the Multiple APIC Description Table (MADT), if exists.
- * Note that this table provides platform SMP configuration
- * information -- the successor to MPS tables.
- */
-
- result = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
- if (!result) {
- return 0;
- }
- else if (result < 0) {
- printk(KERN_ERR PREFIX "Error parsing MADT\n");
- return result;
- }
- else if (result > 1)
- printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n");
-
- /*
- * Local APIC
- * ----------
- * Note that the LAPIC address is obtained from the MADT (32-bit value)
- * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
- */
-
- result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr);
- if (result < 0) {
- printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
- return result;
- }
-
- mp_register_lapic_address(acpi_lapic_addr);
-
- result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic);
- if (!result) {
- printk(KERN_ERR PREFIX "No LAPIC entries present\n");
- /* TBD: Cleanup to allow fallback to MPS */
- return -ENODEV;
- }
- else if (result < 0) {
- printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
- /* TBD: Cleanup to allow fallback to MPS */
- return result;
- }
-
- result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi);
- if (result < 0) {
- printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
- /* TBD: Cleanup to allow fallback to MPS */
- return result;
- }
-
- acpi_lapic = 1;
-
-#endif /*CONFIG_X86_LOCAL_APIC*/
-
-#if defined(CONFIG_X86_IO_APIC) /*&& defined(CONFIG_ACPI_INTERPRETER)*/
-
- /*
- * I/O APIC
- * --------
- */
-
-#if 0
- /*
- * ACPI interpreter is required to complete interrupt setup,
- * so if it is off, don't enumerate the io-apics with ACPI.
- * If MPS is present, it will handle them,
- * otherwise the system will stay in PIC mode
- */
- if (acpi_disabled || acpi_noirq) {
- return 1;
- }
-#endif
-
- /*
- * if "noapic" boot option, don't look for IO-APICs
- */
- if (ioapic_setup_disabled()) {
- printk(KERN_INFO PREFIX "Skipping IOAPIC probe "
- "due to 'noapic' option.\n");
- return 1;
- }
-
-
- result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic);
- if (!result) {
- printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
- return -ENODEV;
- }
- else if (result < 0) {
- printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
- return result;
- }
-
- /* Build a default routing table for legacy (ISA) interrupts. */
- mp_config_acpi_legacy_irqs();
-
- /* Record sci_int for use when looking for MADT sci_int override */
- acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
-
- result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr);
- if (result < 0) {
- printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
- /* TBD: Cleanup to allow fallback to MPS */
- return result;
- }
-
-#ifdef CONFIG_ACPI_INTERPRETER
- /*
- * If BIOS did not supply an INT_SRC_OVR for the SCI
- * pretend we got one so we can set the SCI flags.
- */
- if (!acpi_sci_override_gsi)
- acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
-#endif
-
- result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src);
- if (result < 0) {
- printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
- /* TBD: Cleanup to allow fallback to MPS */
- return result;
- }
-
- acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
-
- acpi_irq_balance_set(NULL);
-
- acpi_ioapic = 1;
-
- if (acpi_lapic && acpi_ioapic)
- smp_found_config = 1;
-
-#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
-
- return 0;
-}
-
-
-#ifdef CONFIG_ACPI_BUS
-/*
- * acpi_pic_sci_set_trigger()
- *
- * use ELCR to set PIC-mode trigger type for SCI
- *
- * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
- * it may require Edge Trigger -- use "acpi_sci=edge"
- *
- * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
- * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge.
- * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0)
- * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
- */
-
-void __init
-acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
-{
- unsigned char mask = 1 << (irq & 7);
- unsigned int port = 0x4d0 + (irq >> 3);
- unsigned char val = inb(port);
-
-
- printk(PREFIX "IRQ%d SCI:", irq);
- if (!(val & mask)) {
- printk(" Edge");
-
- if (trigger == 3) {
- printk(" set to Level");
- outb(val | mask, port);
- }
- } else {
- printk(" Level");
-
- if (trigger == 1) {
- printk(" set to Edge");
- outb(val & ~mask, port);
- }
- }
- printk(" Trigger.\n");
-}
-
-#endif /* CONFIG_ACPI_BUS */
-
-
-/* --------------------------------------------------------------------------
- Low-Level Sleep Support
- -------------------------------------------------------------------------- */
-
-#ifdef CONFIG_ACPI_SLEEP
-
-#define DEBUG
-
-#ifdef DEBUG
-#include <xen/serial.h>
-#endif
-
-/* address in low memory of the wakeup routine. */
-unsigned long acpi_wakeup_address = 0;
-
-/* new page directory that we will be using */
-static pmd_t *pmd;
-
-/* saved page directory */
-static pmd_t saved_pmd;
-
-/* page which we'll use for the new page directory */
-static pte_t *ptep;
-
-extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
-
-/*
- * acpi_create_identity_pmd
- *
- * Create a new, identity mapped pmd.
- *
- * Do this by creating new page directory, and marking all the pages as R/W
- * Then set it as the new Page Middle Directory.
- * And, of course, flush the TLB so it takes effect.
- *
- * We save the address of the old one, for later restoration.
- */
-static void acpi_create_identity_pmd (void)
-{
- pgd_t *pgd;
- int i;
-
- ptep = (pte_t*)__get_free_page(GFP_KERNEL);
-
- /* fill page with low mapping */
- for (i = 0; i < PTRS_PER_PTE; i++)
- set_pte(ptep + i, mk_pte_phys(i << PAGE_SHIFT, PAGE_SHARED));
-
- pgd = pgd_offset(current->active_mm, 0);
- pmd = pmd_alloc(current->mm,pgd, 0);
-
- /* save the old pmd */
- saved_pmd = *pmd;
-
- /* set the new one */
- set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(ptep)));
-
- /* flush the TLB */
- local_flush_tlb();
-}
-
-/*
- * acpi_restore_pmd
- *
- * Restore the old pmd saved by acpi_create_identity_pmd and
- * free the page that said function alloc'd
- */
-static void acpi_restore_pmd (void)
-{
- set_pmd(pmd, saved_pmd);
- local_flush_tlb();
- free_page((unsigned long)ptep);
-}
-
-/**
- * acpi_save_state_mem - save kernel state
- *
- * Create an identity mapped page table and copy the wakeup routine to
- * low memory.
- */
-int acpi_save_state_mem (void)
-{
- acpi_create_identity_pmd();
- acpi_copy_wakeup_routine(acpi_wakeup_address);
-
- return 0;
-}
-
-/**
- * acpi_save_state_disk - save kernel state to disk
- *
- */
-int acpi_save_state_disk (void)
-{
- return 1;
-}
-
-/*
- * acpi_restore_state
- */
-void acpi_restore_state_mem (void)
-{
- acpi_restore_pmd();
-}
-
-/**
- * acpi_reserve_bootmem - do _very_ early ACPI initialisation
- *
- * We allocate a page in low memory for the wakeup
- * routine for when we come back from a sleep state. The
- * runtime allocator allows specification of <16M pages, but not
- * <1M pages.
- */
-void __init acpi_reserve_bootmem(void)
-{
- acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
- if (!acpi_wakeup_address)
- printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
-}
-
-void do_suspend_lowlevel_s4bios(int resume)
-{
- if (!resume) {
- save_processor_context();
- acpi_save_register_state((unsigned long)&&acpi_sleep_done);
- acpi_enter_sleep_state_s4bios();
- return;
- }
-acpi_sleep_done:
- restore_processor_context();
-}
-
-
-#endif /*CONFIG_ACPI_SLEEP*/
-
--- /dev/null
+/*
+ * boot.c - Architecture-Specific Low-Level ACPI Boot Support
+ *
+ * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
+ * Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <xen/config.h>
+#include <xen/errno.h>
+#include <xen/init.h>
+#include <xen/acpi.h>
+#include <xen/irq.h>
+#include <xen/sched.h>
+#include <asm/page.h>
+#include <asm/apic.h>
+#include <asm/io_apic.h>
+#include <asm/apic.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mpspec.h>
+
+int sbf_port; /* XXX XEN */
+
+#ifdef CONFIG_X86_64
+
+static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id) { }
+extern void __init clustered_apic_check(void);
+static inline int ioapic_setup_disabled(void) { return 0; }
+#include <asm/proto.h>
+
+#else /* X86 */
+
+#ifdef CONFIG_X86_LOCAL_APIC
+#include <mach_apic.h>
+#include <mach_mpparse.h>
+#endif /* CONFIG_X86_LOCAL_APIC */
+
+#endif /* X86 */
+
+#define BAD_MADT_ENTRY(entry, end) ( \
+ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \
+ ((acpi_table_entry_header *)entry)->length != sizeof(*entry))
+
+#define PREFIX "ACPI: "
+
+#ifdef CONFIG_ACPI_PCI
+int acpi_noirq __initdata; /* skip ACPI IRQ initialization */
+int acpi_pci_disabled __initdata; /* skip ACPI PCI scan and IRQ initialization */
+#else
+int acpi_noirq __initdata = 1;
+int acpi_pci_disabled __initdata = 1;
+#endif
+int acpi_ht __initdata = 1; /* enable HT */
+
+int acpi_lapic;
+int acpi_ioapic;
+int acpi_strict;
+EXPORT_SYMBOL(acpi_strict);
+
+acpi_interrupt_flags acpi_sci_flags __initdata;
+int acpi_sci_override_gsi __initdata;
+int acpi_skip_timer_override __initdata;
+
+#ifdef CONFIG_X86_LOCAL_APIC
+static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
+#endif
+
+#ifndef __HAVE_ARCH_CMPXCHG
+#warning ACPI uses CMPXCHG, i486 and later hardware
+#endif
+
+#define MAX_MADT_ENTRIES 256
+u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] =
+ { [0 ... MAX_MADT_ENTRIES-1] = 0xff };
+EXPORT_SYMBOL(x86_acpiid_to_apicid);
+
+/* --------------------------------------------------------------------------
+ Boot-time Configuration
+ -------------------------------------------------------------------------- */
+
+/*
+ * The default interrupt routing model is PIC (8259). This gets
+ * overriden if IOAPICs are enumerated (below).
+ */
+enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
+
+#ifdef CONFIG_X86_64
+
+/* rely on all ACPI tables being in the direct mapping */
+char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
+{
+ if (!phys_addr || !size)
+ return NULL;
+
+ if (phys_addr < (end_pfn_map << PAGE_SHIFT))
+ return __va(phys_addr);
+
+ return NULL;
+}
+
+#else
+
+/*
+ * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
+ * to map the target physical address. The problem is that set_fixmap()
+ * provides a single page, and it is possible that the page is not
+ * sufficient.
+ * By using this area, we can map up to MAX_IO_APICS pages temporarily,
+ * i.e. until the next __va_range() call.
+ *
+ * Important Safety Note: The fixed I/O APIC page numbers are *subtracted*
+ * from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and
+ * count idx down while incrementing the phys address.
+ */
+char *__acpi_map_table(unsigned long phys, unsigned long size)
+{
+ unsigned long base, offset, mapped_size;
+ int idx;
+
+ if (phys + size < 8*1024*1024)
+ return __va(phys);
+
+ offset = phys & (PAGE_SIZE - 1);
+ mapped_size = PAGE_SIZE - offset;
+ set_fixmap(FIX_ACPI_END, phys);
+ base = fix_to_virt(FIX_ACPI_END);
+
+ /*
+ * Most cases can be covered by the below.
+ */
+ idx = FIX_ACPI_END;
+ while (mapped_size < size) {
+ if (--idx < FIX_ACPI_BEGIN)
+ return NULL; /* cannot handle this */
+ phys += PAGE_SIZE;
+ set_fixmap(idx, phys);
+ mapped_size += PAGE_SIZE;
+ }
+
+ return ((unsigned char *) base + offset);
+}
+#endif
+
+#ifdef CONFIG_PCI_MMCONFIG
+static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
+{
+ struct acpi_table_mcfg *mcfg;
+
+ if (!phys_addr || !size)
+ return -EINVAL;
+
+ mcfg = (struct acpi_table_mcfg *) __acpi_map_table(phys_addr, size);
+ if (!mcfg) {
+ printk(KERN_WARNING PREFIX "Unable to map MCFG\n");
+ return -ENODEV;
+ }
+
+ if (mcfg->base_reserved) {
+ printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n");
+ return -ENODEV;
+ }
+
+ pci_mmcfg_base_addr = mcfg->base_address;
+
+ return 0;
+}
+#else
+#define acpi_parse_mcfg NULL
+#endif /* !CONFIG_PCI_MMCONFIG */
+
+#ifdef CONFIG_X86_LOCAL_APIC
+static int __init
+acpi_parse_madt (
+ unsigned long phys_addr,
+ unsigned long size)
+{
+ struct acpi_table_madt *madt = NULL;
+
+ if (!phys_addr || !size)
+ return -EINVAL;
+
+ madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size);
+ if (!madt) {
+ printk(KERN_WARNING PREFIX "Unable to map MADT\n");
+ return -ENODEV;
+ }
+
+ if (madt->lapic_address) {
+ acpi_lapic_addr = (u64) madt->lapic_address;
+
+ printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n",
+ madt->lapic_address);
+ }
+
+ acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id);
+
+ return 0;
+}
+
+
+static int __init
+acpi_parse_lapic (
+ acpi_table_entry_header *header, const unsigned long end)
+{
+ struct acpi_table_lapic *processor = NULL;
+
+ processor = (struct acpi_table_lapic*) header;
+
+ if (BAD_MADT_ENTRY(processor, end))
+ return -EINVAL;
+
+ acpi_table_print_madt_entry(header);
+
+ /* no utility in registering a disabled processor */
+ if (processor->flags.enabled == 0)
+ return 0;
+
+ x86_acpiid_to_apicid[processor->acpi_id] = processor->id;
+
+ mp_register_lapic (
+ processor->id, /* APIC ID */
+ processor->flags.enabled); /* Enabled? */
+
+ return 0;
+}
+
+static int __init
+acpi_parse_lapic_addr_ovr (
+ acpi_table_entry_header *header, const unsigned long end)
+{
+ struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;
+
+ lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
+
+ if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
+ return -EINVAL;
+
+ acpi_lapic_addr = lapic_addr_ovr->address;
+
+ return 0;
+}
+
+static int __init
+acpi_parse_lapic_nmi (
+ acpi_table_entry_header *header, const unsigned long end)
+{
+ struct acpi_table_lapic_nmi *lapic_nmi = NULL;
+
+ lapic_nmi = (struct acpi_table_lapic_nmi*) header;
+
+ if (BAD_MADT_ENTRY(lapic_nmi, end))
+ return -EINVAL;
+
+ acpi_table_print_madt_entry(header);
+
+ if (lapic_nmi->lint != 1)
+ printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
+
+ return 0;
+}
+
+
+#endif /*CONFIG_X86_LOCAL_APIC*/
+
+#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
+
+static int __init
+acpi_parse_ioapic (
+ acpi_table_entry_header *header, const unsigned long end)
+{
+ struct acpi_table_ioapic *ioapic = NULL;
+
+ ioapic = (struct acpi_table_ioapic*) header;
+
+ if (BAD_MADT_ENTRY(ioapic, end))
+ return -EINVAL;
+
+ acpi_table_print_madt_entry(header);
+
+ mp_register_ioapic (
+ ioapic->id,
+ ioapic->address,
+ ioapic->global_irq_base);
+
+ return 0;
+}
+
+/*
+ * Parse Interrupt Source Override for the ACPI SCI
+ */
+static void
+acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+{
+ if (trigger == 0) /* compatible SCI trigger is level */
+ trigger = 3;
+
+ if (polarity == 0) /* compatible SCI polarity is low */
+ polarity = 3;
+
+ /* Command-line over-ride via acpi_sci= */
+ if (acpi_sci_flags.trigger)
+ trigger = acpi_sci_flags.trigger;
+
+ if (acpi_sci_flags.polarity)
+ polarity = acpi_sci_flags.polarity;
+
+ /*
+ * mp_config_acpi_legacy_irqs() already setup IRQs < 16
+ * If GSI is < 16, this will update its flags,
+ * else it will create a new mp_irqs[] entry.
+ */
+ mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+
+ /*
+ * stash over-ride to indicate we've been here
+ * and for later update of acpi_fadt
+ */
+ acpi_sci_override_gsi = gsi;
+ return;
+}
+
+static int __init
+acpi_parse_int_src_ovr (
+ acpi_table_entry_header *header, const unsigned long end)
+{
+ struct acpi_table_int_src_ovr *intsrc = NULL;
+
+ intsrc = (struct acpi_table_int_src_ovr*) header;
+
+ if (BAD_MADT_ENTRY(intsrc, end))
+ return -EINVAL;
+
+ acpi_table_print_madt_entry(header);
+
+ if (intsrc->bus_irq == acpi_fadt.sci_int) {
+ acpi_sci_ioapic_setup(intsrc->global_irq,
+ intsrc->flags.polarity, intsrc->flags.trigger);
+ return 0;
+ }
+
+ if (acpi_skip_timer_override &&
+ intsrc->bus_irq == 0 && intsrc->global_irq == 2) {
+ printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
+ return 0;
+ }
+
+ mp_override_legacy_irq (
+ intsrc->bus_irq,
+ intsrc->flags.polarity,
+ intsrc->flags.trigger,
+ intsrc->global_irq);
+
+ return 0;
+}
+
+
+static int __init
+acpi_parse_nmi_src (
+ acpi_table_entry_header *header, const unsigned long end)
+{
+ struct acpi_table_nmi_src *nmi_src = NULL;
+
+ nmi_src = (struct acpi_table_nmi_src*) header;
+
+ if (BAD_MADT_ENTRY(nmi_src, end))
+ return -EINVAL;
+
+ acpi_table_print_madt_entry(header);
+
+ /* TBD: Support nimsrc entries? */
+
+ return 0;
+}
+
+#endif /* CONFIG_X86_IO_APIC */
+
+#ifdef CONFIG_ACPI_BUS
+
+/*
+ * acpi_pic_sci_set_trigger()
+ *
+ * use ELCR to set PIC-mode trigger type for SCI
+ *
+ * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
+ * it may require Edge Trigger -- use "acpi_sci=edge"
+ *
+ * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
+ * for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge.
+ * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0)
+ * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
+ */
+
+void __init
+acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
+{
+ unsigned int mask = 1 << irq;
+ unsigned int old, new;
+
+ /* Real old ELCR mask */
+ old = inb(0x4d0) | (inb(0x4d1) << 8);
+
+ /*
+ * If we use ACPI to set PCI irq's, then we should clear ELCR
+ * since we will set it correctly as we enable the PCI irq
+ * routing.
+ */
+ new = acpi_noirq ? old : 0;
+
+ /*
+ * Update SCI information in the ELCR, it isn't in the PCI
+ * routing tables..
+ */
+ switch (trigger) {
+ case 1: /* Edge - clear */
+ new &= ~mask;
+ break;
+ case 3: /* Level - set */
+ new |= mask;
+ break;
+ }
+
+ if (old == new)
+ return;
+
+ printk(PREFIX "setting ELCR to %04x (from %04x)\n", new, old);
+ outb(new, 0x4d0);
+ outb(new >> 8, 0x4d1);
+}
+
+
+#endif /* CONFIG_ACPI_BUS */
+
+int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
+{
+#ifdef CONFIG_X86_IO_APIC
+ if (use_pci_vector() && !platform_legacy_irq(gsi))
+ *irq = IO_APIC_VECTOR(gsi);
+ else
+#endif
+ *irq = gsi;
+ return 0;
+}
+
+unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
+{
+ unsigned int irq;
+ unsigned int plat_gsi = gsi;
+
+#ifdef CONFIG_PCI
+ /*
+ * Make sure all (legacy) PCI IRQs are set as level-triggered.
+ */
+ if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
+ extern void eisa_set_level_irq(unsigned int irq);
+
+ if (edge_level == ACPI_LEVEL_SENSITIVE)
+ eisa_set_level_irq(gsi);
+ }
+#endif
+
+#ifdef CONFIG_X86_IO_APIC
+ if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
+ plat_gsi = mp_register_gsi(gsi, edge_level, active_high_low);
+ }
+#endif
+ acpi_gsi_to_irq(plat_gsi, &irq);
+ return irq;
+}
+EXPORT_SYMBOL(acpi_register_gsi);
+
+/*
+ * ACPI based hotplug support for CPU
+ */
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+int
+acpi_map_lsapic(acpi_handle handle, int *pcpu)
+{
+ /* TBD */
+ return -EINVAL;
+}
+EXPORT_SYMBOL(acpi_map_lsapic);
+
+
+int
+acpi_unmap_lsapic(int cpu)
+{
+ /* TBD */
+ return -EINVAL;
+}
+EXPORT_SYMBOL(acpi_unmap_lsapic);
+#endif /* CONFIG_ACPI_HOTPLUG_CPU */
+
+static unsigned long __init
+acpi_scan_rsdp (
+ unsigned long start,
+ unsigned long length)
+{
+ unsigned long offset = 0;
+ unsigned long sig_len = sizeof("RSD PTR ") - 1;
+
+ /*
+ * Scan all 16-byte boundaries of the physical memory region for the
+ * RSDP signature.
+ */
+ for (offset = 0; offset < length; offset += 16) {
+ if (strncmp((char *) (start + offset), "RSD PTR ", sig_len))
+ continue;
+ return (start + offset);
+ }
+
+ return 0;
+}
+
+static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size)
+{
+ struct acpi_table_sbf *sb;
+
+ if (!phys_addr || !size)
+ return -EINVAL;
+
+ sb = (struct acpi_table_sbf *) __acpi_map_table(phys_addr, size);
+ if (!sb) {
+ printk(KERN_WARNING PREFIX "Unable to map SBF\n");
+ return -ENODEV;
+ }
+
+ sbf_port = sb->sbf_cmos; /* Save CMOS port */
+
+ return 0;
+}
+
+
+#ifdef CONFIG_HPET_TIMER
+
+static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
+{
+ struct acpi_table_hpet *hpet_tbl;
+
+ if (!phys || !size)
+ return -EINVAL;
+
+ hpet_tbl = (struct acpi_table_hpet *) __acpi_map_table(phys, size);
+ if (!hpet_tbl) {
+ printk(KERN_WARNING PREFIX "Unable to map HPET\n");
+ return -ENODEV;
+ }
+
+ if (hpet_tbl->addr.space_id != ACPI_SPACE_MEM) {
+ printk(KERN_WARNING PREFIX "HPET timers must be located in "
+ "memory.\n");
+ return -1;
+ }
+
+#ifdef CONFIG_X86_64
+ vxtime.hpet_address = hpet_tbl->addr.addrl |
+ ((long) hpet_tbl->addr.addrh << 32);
+
+ printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
+ hpet_tbl->id, vxtime.hpet_address);
+#else /* X86 */
+ {
+ extern unsigned long hpet_address;
+
+ hpet_address = hpet_tbl->addr.addrl;
+ printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
+ hpet_tbl->id, hpet_address);
+ }
+#endif /* X86 */
+
+ return 0;
+}
+#else
+#define acpi_parse_hpet NULL
+#endif
+
+#ifdef CONFIG_X86_PM_TIMER
+extern u32 pmtmr_ioport;
+#endif
+
+static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
+{
+ struct fadt_descriptor_rev2 *fadt = NULL;
+
+ fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size);
+ if(!fadt) {
+ printk(KERN_WARNING PREFIX "Unable to map FADT\n");
+ return 0;
+ }
+
+#ifdef CONFIG_ACPI_INTERPRETER
+ /* initialize sci_int early for INT_SRC_OVR MADT parsing */
+ acpi_fadt.sci_int = fadt->sci_int;
+#endif
+
+#ifdef CONFIG_X86_PM_TIMER
+ /* detect the location of the ACPI PM Timer */
+ if (fadt->revision >= FADT2_REVISION_ID) {
+ /* FADT rev. 2 */
+ if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO)
+ return 0;
+
+ pmtmr_ioport = fadt->xpm_tmr_blk.address;
+ } else {
+ /* FADT rev. 1 */
+ pmtmr_ioport = fadt->V1_pm_tmr_blk;
+ }
+ if (pmtmr_ioport)
+ printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport);
+#endif
+ return 0;
+}
+
+
+unsigned long __init
+acpi_find_rsdp (void)
+{
+ unsigned long rsdp_phys = 0;
+
+#if 0
+ if (efi_enabled) {
+ if (efi.acpi20)
+ return __pa(efi.acpi20);
+ else if (efi.acpi)
+ return __pa(efi.acpi);
+ }
+#endif
+ /*
+ * Scan memory looking for the RSDP signature. First search EBDA (low
+ * memory) paragraphs and then search upper memory (E0000-FFFFF).
+ */
+ rsdp_phys = acpi_scan_rsdp (0, 0x400);
+ if (!rsdp_phys)
+ rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF);
+
+ return rsdp_phys;
+}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+/*
+ * Parse LAPIC entries in MADT
+ * returns 0 on success, < 0 on error
+ */
+static int __init
+acpi_parse_madt_lapic_entries(void)
+{
+ int count;
+
+ /*
+ * Note that the LAPIC address is obtained from the MADT (32-bit value)
+ * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
+ */
+
+ count = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0);
+ if (count < 0) {
+ printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
+ return count;
+ }
+
+ mp_register_lapic_address(acpi_lapic_addr);
+
+ count = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic,
+ MAX_APICS);
+ if (!count) {
+ printk(KERN_ERR PREFIX "No LAPIC entries present\n");
+ /* TBD: Cleanup to allow fallback to MPS */
+ return -ENODEV;
+ }
+ else if (count < 0) {
+ printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
+ /* TBD: Cleanup to allow fallback to MPS */
+ return count;
+ }
+
+ count = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0);
+ if (count < 0) {
+ printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
+ /* TBD: Cleanup to allow fallback to MPS */
+ return count;
+ }
+ return 0;
+}
+#endif /* CONFIG_X86_LOCAL_APIC */
+
+#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
+/*
+ * Parse IOAPIC related entries in MADT
+ * returns 0 on success, < 0 on error
+ */
+static int __init
+acpi_parse_madt_ioapic_entries(void)
+{
+ int count;
+
+ /*
+ * ACPI interpreter is required to complete interrupt setup,
+ * so if it is off, don't enumerate the io-apics with ACPI.
+ * If MPS is present, it will handle them,
+ * otherwise the system will stay in PIC mode
+ */
+ if (acpi_disabled || acpi_noirq) {
+ return -ENODEV;
+ }
+
+ /*
+ * if "noapic" boot option, don't look for IO-APICs
+ */
+ if (skip_ioapic_setup) {
+ printk(KERN_INFO PREFIX "Skipping IOAPIC probe "
+ "due to 'noapic' option.\n");
+ return -ENODEV;
+ }
+
+ count = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic, MAX_IO_APICS);
+ if (!count) {
+ printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
+ return -ENODEV;
+ }
+ else if (count < 0) {
+ printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
+ return count;
+ }
+
+ count = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS);
+ if (count < 0) {
+ printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
+ /* TBD: Cleanup to allow fallback to MPS */
+ return count;
+ }
+
+ /*
+ * If BIOS did not supply an INT_SRC_OVR for the SCI
+ * pretend we got one so we can set the SCI flags.
+ */
+ if (!acpi_sci_override_gsi)
+ acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
+
+ /* Fill in identity legacy mapings where no override */
+ mp_config_acpi_legacy_irqs();
+
+ count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS);
+ if (count < 0) {
+ printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
+ /* TBD: Cleanup to allow fallback to MPS */
+ return count;
+ }
+
+ return 0;
+}
+#else
+static inline int acpi_parse_madt_ioapic_entries(void)
+{
+ return -1;
+}
+#endif /* !(CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER) */
+
+
+static void __init
+acpi_process_madt(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+ int count, error;
+
+ count = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
+ if (count >= 1) {
+
+ /*
+ * Parse MADT LAPIC entries
+ */
+ error = acpi_parse_madt_lapic_entries();
+ if (!error) {
+ acpi_lapic = 1;
+
+ /*
+ * Parse MADT IO-APIC entries
+ */
+ error = acpi_parse_madt_ioapic_entries();
+ if (!error) {
+ acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
+ acpi_irq_balance_set(NULL);
+ acpi_ioapic = 1;
+
+ smp_found_config = 1;
+ clustered_apic_check();
+ }
+ }
+ if (error == -EINVAL) {
+ /*
+ * Dell Precision Workstation 410, 610 come here.
+ */
+ printk(KERN_ERR PREFIX "Invalid BIOS MADT, disabling ACPI\n");
+ disable_acpi();
+ }
+ }
+#endif
+ return;
+}
+
+/*
+ * acpi_boot_table_init() and acpi_boot_init()
+ * called from setup_arch(), always.
+ * 1. checksums all tables
+ * 2. enumerates lapics
+ * 3. enumerates io-apics
+ *
+ * acpi_table_init() is separate to allow reading SRAT without
+ * other side effects.
+ *
+ * side effects of acpi_boot_init:
+ * acpi_lapic = 1 if LAPIC found
+ * acpi_ioapic = 1 if IOAPIC found
+ * if (acpi_lapic && acpi_ioapic) smp_found_config = 1;
+ * if acpi_blacklisted() acpi_disabled = 1;
+ * acpi_irq_model=...
+ * ...
+ *
+ * return value: (currently ignored)
+ * 0: success
+ * !0: failure
+ */
+
+int __init
+acpi_boot_table_init(void)
+{
+ int error;
+
+ /*
+ * If acpi_disabled, bail out
+ * One exception: acpi=ht continues far enough to enumerate LAPICs
+ */
+ if (acpi_disabled && !acpi_ht)
+ return 1;
+
+ /*
+ * Initialize the ACPI boot-time table parser.
+ */
+ error = acpi_table_init();
+ if (error) {
+ disable_acpi();
+ return error;
+ }
+
+#if 0 /*def __i386__*/
+ check_acpi_pci();
+#endif
+
+ acpi_table_parse(ACPI_BOOT, acpi_parse_sbf);
+
+ /*
+ * blacklist may disable ACPI entirely
+ */
+ error = acpi_blacklisted();
+ if (error) {
+ extern int acpi_force;
+
+ if (acpi_force) {
+ printk(KERN_WARNING PREFIX "acpi=force override\n");
+ } else {
+ printk(KERN_WARNING PREFIX "Disabling ACPI support\n");
+ disable_acpi();
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+
+int __init acpi_boot_init(void)
+{
+ /*
+ * If acpi_disabled, bail out
+ * One exception: acpi=ht continues far enough to enumerate LAPICs
+ */
+ if (acpi_disabled && !acpi_ht)
+ return 1;
+
+ acpi_table_parse(ACPI_BOOT, acpi_parse_sbf);
+
+ /*
+ * set sci_int and PM timer address
+ */
+ acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
+
+ /*
+ * Process the Multiple APIC Description Table (MADT), if present
+ */
+ acpi_process_madt();
+
+ acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
+ acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
+
+ return 0;
+}
+
#include <asm/hardirq.h>
#include <asm/apic.h>
#include <asm/io_apic.h>
-#include <asm/mach_apic.h>
-#include <asm/io_ports.h>
+#include <mach_apic.h>
+#include <io_ports.h>
/* Using APIC to generate smp_local_timer_interrupt? */
int using_apic_timer = 0;
+int apic_verbosity;
+
static int enabled_via_apicbase;
+int get_physical_broadcast(void)
+{
+ unsigned int lvr, version;
+ lvr = apic_read(APIC_LVR);
+ version = GET_APIC_VERSION(lvr);
+ if (!APIC_INTEGRATED(version) || version >= 0x14)
+ return 0xff;
+ else
+ return 0xf;
+}
+
int get_maxlvt(void)
{
unsigned int v, ver, maxlvt;
#ifdef CONFIG_SMP
cpu_online_map = 1;
#endif
- phys_cpu_present_map = 1;
+ phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
apic_write_around(APIC_ID, boot_cpu_physical_apicid);
setup_local_APIC();
/*
* ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
- * (these are usually mapped to vectors 0x30-0x3f)
+ * (these are usually mapped to vectors 0x20-0x2f)
*/
BUILD_16_IRQS(0x0)
* of these. Plus, more powerful systems might have more than 64
* IO-APIC registers.
*
- * (these are usually mapped into the 0x30-0xff vector range)
+ * (these are usually mapped into the 0x20-0xff vector range)
*/
BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
- void *interrupt[NR_IRQS] = {
+ void (*interrupt[NR_IRQS])(void) = {
IRQLIST_16(0x0),
#ifdef CONFIG_X86_IO_APIC
* outb_p - this has to work on a wide range of PC hardware.
*/
outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */
- outb_p(0x30 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */
+ outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */
if (auto_eoi)
outb_p(0x03, 0x21); /* master does Auto EOI */
outb_p(0x01, 0x21); /* master expects normal EOI */
outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */
- outb_p(0x30 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x38-0x3f */
+ outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */
outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode
is to be investigated) */
#include <xen/irq.h>
#include <xen/delay.h>
#include <xen/sched.h>
-#include <xen/config.h>
-#include <asm/mc146818rtc.h>
+#include <xen/acpi.h>
#include <asm/io.h>
-#include <asm/mpspec.h>
-#include <asm/io_apic.h>
+#include <asm/mc146818rtc.h>
#include <asm/smp.h>
#include <asm/desc.h>
-#include <asm/smpboot.h>
-
-#ifdef CONFIG_X86_IO_APIC
+#include <mach_apic.h>
+#include <io_ports.h>
-#undef APIC_LOCKUP_DEBUG
+int (*ioapic_renumber_irq)(int ioapic, int irq);
+atomic_t irq_mis_count;
-#define APIC_LOCKUP_DEBUG
-
-static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;
-
-unsigned int int_dest_addr_mode = APIC_DEST_LOGICAL;
-unsigned char int_delivery_mode = dest_LowestPrio;
+static DEFINE_SPINLOCK(ioapic_lock);
+int skip_ioapic_setup;
/*
* # of IRQ routing registers
int apic, pin, next;
} irq_2_pin[PIN_MAP_SIZE];
+int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
+#ifdef CONFIG_PCI_MSI
+#define vector_to_irq(vector) \
+ (platform_legacy_irq(vector) ? vector : vector_irq[vector])
+#else
+#define vector_to_irq(vector) (vector)
+#endif
+
/*
* The common case is 1:1 IRQ<->pin mappings. Sometimes there are
* shared ISA-space IRQs, so we have to support them. We are super
* fast in the common case, and fast for shared ISA-space IRQs.
*/
-static void __init add_pin_to_irq(unsigned int irq, int apic, int pin)
+static void add_pin_to_irq(unsigned int irq, int apic, int pin)
{
static int first_free_entry = NR_IRQS;
struct irq_pin_list *entry = irq_2_pin + irq;
}
}
-#define __DO_ACTION(R, ACTION, FINAL) \
- \
-{ \
- int pin; \
- struct irq_pin_list *entry = irq_2_pin + irq; \
- \
- for (;;) { \
- unsigned int reg; \
- pin = entry->pin; \
- if (pin == -1) \
- break; \
- reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \
- reg ACTION; \
- io_apic_write(entry->apic, 0x10 + R + pin*2, reg); \
- if (!entry->next) \
- break; \
- entry = irq_2_pin + entry->next; \
- } \
- FINAL; \
-}
-
-#define DO_ACTION(name,R,ACTION, FINAL) \
- \
- static void name##_IO_APIC_irq (unsigned int irq) \
- __DO_ACTION(R, ACTION, FINAL)
-
-DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic) )
-DO_ACTION( __unmask, 0, &= 0xfffeffff, )
-DO_ACTION( __edge, 0, &= 0xffff7fff, )
-DO_ACTION( __level, 0, |= 0x00008000, )
+static void __modify_IO_APIC_irq (unsigned int irq, unsigned long enable, unsigned long disable)
+{
+ struct irq_pin_list *entry = irq_2_pin + irq;
+ unsigned int pin, reg;
+
+ for (;;) {
+ pin = entry->pin;
+ if (pin == -1)
+ break;
+ reg = io_apic_read(entry->apic, 0x10 + pin*2);
+ reg &= ~disable;
+ reg |= enable;
+ io_apic_modify(entry->apic, 0x10 + pin*2, reg);
+ if (!entry->next)
+ break;
+ entry = irq_2_pin + entry->next;
+ }
+}
+
+/* mask = 1 */
+static void __mask_IO_APIC_irq (unsigned int irq)
+{
+ __modify_IO_APIC_irq(irq, 0x00010000, 0);
+}
+
+/* mask = 0 */
+static void __unmask_IO_APIC_irq (unsigned int irq)
+{
+ __modify_IO_APIC_irq(irq, 0, 0x00010000);
+}
+
+/* mask = 1, trigger = 0 */
+static void __mask_and_edge_IO_APIC_irq (unsigned int irq)
+{
+ __modify_IO_APIC_irq(irq, 0x00010000, 0x00008000);
+}
+
+/* mask = 0, trigger = 1 */
+static void __unmask_and_level_IO_APIC_irq (unsigned int irq)
+{
+ __modify_IO_APIC_irq(irq, 0x00008000, 0x00010000);
+}
static void mask_IO_APIC_irq (unsigned int irq)
{
{
struct IO_APIC_route_entry entry;
unsigned long flags;
-
+
/* Check delivery_mode to be sure we're not clearing an SMI pin */
spin_lock_irqsave(&ioapic_lock, flags);
*(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
clear_IO_APIC_pin(apic, pin);
}
-static void set_ioapic_affinity (unsigned int irq, unsigned long mask)
+static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
{
unsigned long flags;
-
- /*
- * Only the first 8 bits are valid.
- */
- mask = mask << 24;
+ int pin;
+ struct irq_pin_list *entry = irq_2_pin + irq;
+ unsigned int apicid_value;
+
+ apicid_value = cpu_mask_to_apicid(cpumask);
+ /* Prepare to do the io_apic_write */
+ apicid_value = apicid_value << 24;
spin_lock_irqsave(&ioapic_lock, flags);
- __DO_ACTION(1, = mask, )
+ for (;;) {
+ pin = entry->pin;
+ if (pin == -1)
+ break;
+ io_apic_write(entry->apic, 0x10 + 1 + pin*2, apicid_value);
+ if (!entry->next)
+ break;
+ entry = irq_2_pin + entry->next;
+ }
spin_unlock_irqrestore(&ioapic_lock, flags);
}
-#define balance_irq(_irq) ((void)0)
+#if defined(CONFIG_IRQBALANCE)
+# include <asm/processor.h> /* kernel_thread() */
+# include <xen/kernel_stat.h> /* kstat */
+# include <xen/slab.h> /* kmalloc() */
+# include <xen/timer.h> /* time_after() */
+
+# ifdef CONFIG_BALANCED_IRQ_DEBUG
+# define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0)
+# define Dprintk(x...) do { TDprintk(x); } while (0)
+# else
+# define TDprintk(x...)
+# define Dprintk(x...)
+# endif
-/*
- * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
- * specific CPU-side IRQs.
- */
+cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS];
-#define MAX_PIRQS 8
-int pirq_entries [MAX_PIRQS];
-int pirqs_enabled;
+#define IRQBALANCE_CHECK_ARCH -999
+static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
+static int physical_balance = 0;
-int skip_ioapic_setup;
-#if 0
+struct irq_cpu_info {
+ unsigned long * last_irq;
+ unsigned long * irq_delta;
+ unsigned long irq;
+} irq_cpu_data[NR_CPUS];
+
+#define CPU_IRQ(cpu) (irq_cpu_data[cpu].irq)
+#define LAST_CPU_IRQ(cpu,irq) (irq_cpu_data[cpu].last_irq[irq])
+#define IRQ_DELTA(cpu,irq) (irq_cpu_data[cpu].irq_delta[irq])
-static int __init noioapic_setup(char *str)
+#define IDLE_ENOUGH(cpu,now) \
+ (idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1))
+
+#define IRQ_ALLOWED(cpu, allowed_mask) cpu_isset(cpu, allowed_mask)
+
+#define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i]))
+
+#define MAX_BALANCED_IRQ_INTERVAL (5*HZ)
+#define MIN_BALANCED_IRQ_INTERVAL (HZ/2)
+#define BALANCED_IRQ_MORE_DELTA (HZ/10)
+#define BALANCED_IRQ_LESS_DELTA (HZ)
+
+long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
+
+static unsigned long move(int curr_cpu, cpumask_t allowed_mask,
+ unsigned long now, int direction)
{
- skip_ioapic_setup = 1;
- return 1;
+ int search_idle = 1;
+ int cpu = curr_cpu;
+
+ goto inside;
+
+ do {
+ if (unlikely(cpu == curr_cpu))
+ search_idle = 0;
+inside:
+ if (direction == 1) {
+ cpu++;
+ if (cpu >= NR_CPUS)
+ cpu = 0;
+ } else {
+ cpu--;
+ if (cpu == -1)
+ cpu = NR_CPUS-1;
+ }
+ } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
+ (search_idle && !IDLE_ENOUGH(cpu,now)));
+
+ return cpu;
}
-__setup("noapic", noioapic_setup);
+static inline void balance_irq(int cpu, int irq)
+{
+ unsigned long now = jiffies;
+ cpumask_t allowed_mask;
+ unsigned int new_cpu;
+
+ if (irqbalance_disabled)
+ return;
+
+ cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]);
+ new_cpu = move(cpu, allowed_mask, now, 1);
+ if (cpu != new_cpu) {
+ irq_desc_t *desc = irq_desc + irq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ pending_irq_balance_cpumask[irq] = cpumask_of_cpu(new_cpu);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
-static int __init ioapic_setup(char *str)
+static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
{
- skip_ioapic_setup = 0;
- return 1;
+ int i, j;
+ Dprintk("Rotating IRQs among CPUs.\n");
+ for (i = 0; i < NR_CPUS; i++) {
+ for (j = 0; cpu_online(i) && (j < NR_IRQS); j++) {
+ if (!irq_desc[j].action)
+ continue;
+ /* Is it a significant load ? */
+ if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) <
+ useful_load_threshold)
+ continue;
+ balance_irq(i, j);
+ }
+ }
+ balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL,
+ balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
+ return;
}
-__setup("apic", ioapic_setup);
+static void do_irq_balance(void)
+{
+ int i, j;
+ unsigned long max_cpu_irq = 0, min_cpu_irq = (~0);
+ unsigned long move_this_load = 0;
+ int max_loaded = 0, min_loaded = 0;
+ int load;
+ unsigned long useful_load_threshold = balanced_irq_interval + 10;
+ int selected_irq;
+ int tmp_loaded, first_attempt = 1;
+ unsigned long tmp_cpu_irq;
+ unsigned long imbalance = 0;
+ cpumask_t allowed_mask, target_cpu_mask, tmp;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ int package_index;
+ CPU_IRQ(i) = 0;
+ if (!cpu_online(i))
+ continue;
+ package_index = CPU_TO_PACKAGEINDEX(i);
+ for (j = 0; j < NR_IRQS; j++) {
+ unsigned long value_now, delta;
+ /* Is this an active IRQ? */
+ if (!irq_desc[j].action)
+ continue;
+ if ( package_index == i )
+ IRQ_DELTA(package_index,j) = 0;
+ /* Determine the total count per processor per IRQ */
+ value_now = (unsigned long) kstat_cpu(i).irqs[j];
+
+ /* Determine the activity per processor per IRQ */
+ delta = value_now - LAST_CPU_IRQ(i,j);
+
+ /* Update last_cpu_irq[][] for the next time */
+ LAST_CPU_IRQ(i,j) = value_now;
+
+ /* Ignore IRQs whose rate is less than the clock */
+ if (delta < useful_load_threshold)
+ continue;
+ /* update the load for the processor or package total */
+ IRQ_DELTA(package_index,j) += delta;
+
+ /* Keep track of the higher numbered sibling as well */
+ if (i != package_index)
+ CPU_IRQ(i) += delta;
+ /*
+ * We have sibling A and sibling B in the package
+ *
+ * cpu_irq[A] = load for cpu A + load for cpu B
+ * cpu_irq[B] = load for cpu B
+ */
+ CPU_IRQ(package_index) += delta;
+ }
+ }
+ /* Find the least loaded processor package */
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
+ if (i != CPU_TO_PACKAGEINDEX(i))
+ continue;
+ if (min_cpu_irq > CPU_IRQ(i)) {
+ min_cpu_irq = CPU_IRQ(i);
+ min_loaded = i;
+ }
+ }
+ max_cpu_irq = ULONG_MAX;
+
+tryanothercpu:
+ /* Look for heaviest loaded processor.
+ * We may come back to get the next heaviest loaded processor.
+ * Skip processors with trivial loads.
+ */
+ tmp_cpu_irq = 0;
+ tmp_loaded = -1;
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
+ if (i != CPU_TO_PACKAGEINDEX(i))
+ continue;
+ if (max_cpu_irq <= CPU_IRQ(i))
+ continue;
+ if (tmp_cpu_irq < CPU_IRQ(i)) {
+ tmp_cpu_irq = CPU_IRQ(i);
+ tmp_loaded = i;
+ }
+ }
+
+ if (tmp_loaded == -1) {
+ /* In the case of small number of heavy interrupt sources,
+ * loading some of the cpus too much. We use Ingo's original
+ * approach to rotate them around.
+ */
+ if (!first_attempt && imbalance >= useful_load_threshold) {
+ rotate_irqs_among_cpus(useful_load_threshold);
+ return;
+ }
+ goto not_worth_the_effort;
+ }
+
+ first_attempt = 0; /* heaviest search */
+ max_cpu_irq = tmp_cpu_irq; /* load */
+ max_loaded = tmp_loaded; /* processor */
+ imbalance = (max_cpu_irq - min_cpu_irq) / 2;
+
+ Dprintk("max_loaded cpu = %d\n", max_loaded);
+ Dprintk("min_loaded cpu = %d\n", min_loaded);
+ Dprintk("max_cpu_irq load = %ld\n", max_cpu_irq);
+ Dprintk("min_cpu_irq load = %ld\n", min_cpu_irq);
+ Dprintk("load imbalance = %lu\n", imbalance);
+
+ /* if imbalance is less than approx 10% of max load, then
+ * observe diminishing returns action. - quit
+ */
+ if (imbalance < (max_cpu_irq >> 3)) {
+ Dprintk("Imbalance too trivial\n");
+ goto not_worth_the_effort;
+ }
+
+tryanotherirq:
+ /* if we select an IRQ to move that can't go where we want, then
+ * see if there is another one to try.
+ */
+ move_this_load = 0;
+ selected_irq = -1;
+ for (j = 0; j < NR_IRQS; j++) {
+ /* Is this an active IRQ? */
+ if (!irq_desc[j].action)
+ continue;
+ if (imbalance <= IRQ_DELTA(max_loaded,j))
+ continue;
+ /* Try to find the IRQ that is closest to the imbalance
+ * without going over.
+ */
+ if (move_this_load < IRQ_DELTA(max_loaded,j)) {
+ move_this_load = IRQ_DELTA(max_loaded,j);
+ selected_irq = j;
+ }
+ }
+ if (selected_irq == -1) {
+ goto tryanothercpu;
+ }
+
+ imbalance = move_this_load;
+
+ /* For physical_balance case, we accumlated both load
+ * values in the one of the siblings cpu_irq[],
+ * to use the same code for physical and logical processors
+ * as much as possible.
+ *
+ * NOTE: the cpu_irq[] array holds the sum of the load for
+ * sibling A and sibling B in the slot for the lowest numbered
+ * sibling (A), _AND_ the load for sibling B in the slot for
+ * the higher numbered sibling.
+ *
+ * We seek the least loaded sibling by making the comparison
+ * (A+B)/2 vs B
+ */
+ load = CPU_IRQ(min_loaded) >> 1;
+ for_each_cpu_mask(j, cpu_sibling_map[min_loaded]) {
+ if (load > CPU_IRQ(j)) {
+ /* This won't change cpu_sibling_map[min_loaded] */
+ load = CPU_IRQ(j);
+ min_loaded = j;
+ }
+ }
+
+ cpus_and(allowed_mask, cpu_online_map, irq_affinity[selected_irq]);
+ target_cpu_mask = cpumask_of_cpu(min_loaded);
+ cpus_and(tmp, target_cpu_mask, allowed_mask);
+
+ if (!cpus_empty(tmp)) {
+ irq_desc_t *desc = irq_desc + selected_irq;
+ unsigned long flags;
+
+ Dprintk("irq = %d moved to cpu = %d\n",
+ selected_irq, min_loaded);
+ /* mark for change destination */
+ spin_lock_irqsave(&desc->lock, flags);
+ pending_irq_balance_cpumask[selected_irq] =
+ cpumask_of_cpu(min_loaded);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ /* Since we made a change, come back sooner to
+ * check for more variation.
+ */
+ balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL,
+ balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
+ return;
+ }
+ goto tryanotherirq;
+
+not_worth_the_effort:
+ /*
+ * if we did not find an IRQ to move, then adjust the time interval
+ * upward
+ */
+ balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL,
+ balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);
+ Dprintk("IRQ worth rotating not found\n");
+ return;
+}
+static int balanced_irq(void *unused)
+{
+ int i;
+ unsigned long prev_balance_time = jiffies;
+ long time_remaining = balanced_irq_interval;
+
+ daemonize("kirqd");
+
+ /* push everything to CPU 0 to give us a starting point. */
+ for (i = 0 ; i < NR_IRQS ; i++) {
+ pending_irq_balance_cpumask[i] = cpumask_of_cpu(0);
+ }
+ for ( ; ; ) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ time_remaining = schedule_timeout(time_remaining);
+ try_to_freeze(PF_FREEZE);
+ if (time_after(jiffies,
+ prev_balance_time+balanced_irq_interval)) {
+ do_irq_balance();
+ prev_balance_time = jiffies;
+ time_remaining = balanced_irq_interval;
+ }
+ }
+ return 0;
+}
-static int __init ioapic_pirq_setup(char *str)
+static int __init balanced_irq_init(void)
{
- int i, max;
- int ints[MAX_PIRQS+1];
+ int i;
+ struct cpuinfo_x86 *c;
+ cpumask_t tmp;
+
+ cpus_shift_right(tmp, cpu_online_map, 2);
+ c = &boot_cpu_data;
+ /* When not overwritten by the command line ask subarchitecture. */
+ if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH)
+ irqbalance_disabled = NO_BALANCE_IRQ;
+ if (irqbalance_disabled)
+ return 0;
+
+ /* disable irqbalance completely if there is only one processor online */
+ if (num_online_cpus() < 2) {
+ irqbalance_disabled = 1;
+ return 0;
+ }
+ /*
+ * Enable physical balance only if more than 1 physical processor
+ * is present
+ */
+ if (smp_num_siblings > 1 && !cpus_empty(tmp))
+ physical_balance = 1;
- get_options(str, ARRAY_SIZE(ints), ints);
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_online(i))
+ continue;
+ irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+ irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+ if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) {
+ printk(KERN_ERR "balanced_irq_init: out of memory");
+ goto failed;
+ }
+ memset(irq_cpu_data[i].irq_delta,0,sizeof(unsigned long) * NR_IRQS);
+ memset(irq_cpu_data[i].last_irq,0,sizeof(unsigned long) * NR_IRQS);
+ }
+
+ printk(KERN_INFO "Starting balanced_irq\n");
+ if (kernel_thread(balanced_irq, NULL, CLONE_KERNEL) >= 0)
+ return 0;
+ else
+ printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
+failed:
+ for (i = 0; i < NR_CPUS; i++) {
+ if(irq_cpu_data[i].irq_delta)
+ kfree(irq_cpu_data[i].irq_delta);
+ if(irq_cpu_data[i].last_irq)
+ kfree(irq_cpu_data[i].last_irq);
+ }
+ return 0;
+}
- for (i = 0; i < MAX_PIRQS; i++)
- pirq_entries[i] = -1;
+int __init irqbalance_disable(char *str)
+{
+ irqbalance_disabled = 1;
+ return 0;
+}
- pirqs_enabled = 1;
- printk(KERN_INFO "PIRQ redirection, working around broken MP-BIOS.\n");
- max = MAX_PIRQS;
- if (ints[0] < MAX_PIRQS)
- max = ints[0];
+__setup("noirqbalance", irqbalance_disable);
- for (i = 0; i < max; i++) {
- printk(KERN_DEBUG "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
- /*
- * PIRQs are mapped upside down, usually.
- */
- pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
+static inline void move_irq(int irq)
+{
+ /* note - we hold the desc->lock */
+ if (unlikely(!cpus_empty(pending_irq_balance_cpumask[irq]))) {
+ set_ioapic_affinity_irq(irq, pending_irq_balance_cpumask[irq]);
+ cpus_clear(pending_irq_balance_cpumask[irq]);
}
- return 1;
}
-__setup("pirq=", ioapic_pirq_setup);
+late_initcall(balanced_irq_init);
-#endif
+#else /* !CONFIG_IRQBALANCE */
+static inline void move_irq(int irq) { }
+#endif /* CONFIG_IRQBALANCE */
+
+#ifndef CONFIG_SMP
+void fastcall send_IPI_self(int vector)
+{
+ unsigned int cfg;
+
+ /*
+ * Wait for idle.
+ */
+ apic_wait_icr_idle();
+ cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
+ /*
+ * Send the IPI. The write to APIC_ICR fires this off.
+ */
+ apic_write_around(APIC_ICR, cfg);
+}
+#endif /* !CONFIG_SMP */
/*
* Find the IRQ entry number of a certain pin.
*/
-static int __init find_irq_entry(int apic, int pin, int type)
+static int find_irq_entry(int apic, int pin, int type)
{
int i;
/*
* Find the pin to which IRQ[irq] (ISA) is connected
*/
-static int __init find_isa_irq_pin(int irq, int type)
+static int find_isa_irq_pin(int irq, int type)
{
int i;
if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
- mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
+ mp_bus_id_to_type[lbus] == MP_BUS_MCA ||
+ mp_bus_id_to_type[lbus] == MP_BUS_NEC98
+ ) &&
(mp_irqs[i].mpc_irqtype == type) &&
(mp_irqs[i].mpc_srcbusirq == irq))
*/
static int pin_2_irq(int idx, int apic, int pin);
+int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
+{
+ int apic, i, best_guess = -1;
+
+ apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, "
+ "slot:%d, pin:%d.\n", bus, slot, pin);
+ if (mp_bus_id_to_pci_bus[bus] == -1) {
+ printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+ return -1;
+ }
+ for (i = 0; i < mp_irq_entries; i++) {
+ int lbus = mp_irqs[i].mpc_srcbus;
+
+ for (apic = 0; apic < nr_ioapics; apic++)
+ if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic ||
+ mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
+ break;
+
+ if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
+ !mp_irqs[i].mpc_irqtype &&
+ (bus == lbus) &&
+ (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
+ int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
+
+ if (!(apic || IO_APIC_IRQ(irq)))
+ continue;
+
+ if (pin == (mp_irqs[i].mpc_srcbusirq & 3))
+ return irq;
+ /*
+ * Use the first all-but-pin matching entry as a
+ * best-guess fuzzy result for broken mptables.
+ */
+ if (best_guess < 0)
+ best_guess = irq;
+ }
+ }
+ return best_guess;
+}
+
+/*
+ * This function currently is only a helper for the i386 smp boot process where
+ * we need to reprogram the ioredtbls to cater for the cpus which have come online
+ * so mask in all cases should simply be TARGET_CPUS
+ */
+void __init setup_ioapic_dest(void)
+{
+ int pin, ioapic, irq, irq_entry;
+
+ if (skip_ioapic_setup == 1)
+ return;
+
+ for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
+ for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+ irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+ if (irq_entry == -1)
+ continue;
+ irq = pin_2_irq(irq_entry, ioapic, pin);
+ set_ioapic_affinity_irq(irq, TARGET_CPUS);
+ }
+
+ }
+}
+
/*
* EISA Edge/Level control register, ELCR
*/
-static int __init EISA_ELCR(unsigned int irq)
+static int EISA_ELCR(unsigned int irq)
{
if (irq < 16) {
unsigned int port = 0x4d0 + (irq >> 3);
return (inb(port) >> (irq & 7)) & 1;
}
- printk(KERN_INFO "Broken MPtable reports ISA irq %d\n", irq);
+ apic_printk(APIC_VERBOSE, KERN_INFO
+ "Broken MPtable reports ISA irq %d\n", irq);
return 0;
}
#define default_MCA_trigger(idx) (1)
#define default_MCA_polarity(idx) (0)
+/* NEC98 interrupts are always polarity zero edge triggered,
+ * when listed as conforming in the MP table. */
+
+#define default_NEC98_trigger(idx) (0)
+#define default_NEC98_polarity(idx) (0)
+
static int __init MPBIOS_polarity(int idx)
{
int bus = mp_irqs[idx].mpc_srcbus;
polarity = default_MCA_polarity(idx);
break;
}
+ case MP_BUS_NEC98: /* NEC 98 pin */
+ {
+ polarity = default_NEC98_polarity(idx);
+ break;
+ }
default:
{
printk(KERN_WARNING "broken BIOS!!\n");
return polarity;
}
-static int __init MPBIOS_trigger(int idx)
+static int MPBIOS_trigger(int idx)
{
int bus = mp_irqs[idx].mpc_srcbus;
int trigger;
trigger = default_MCA_trigger(idx);
break;
}
+ case MP_BUS_NEC98: /* NEC 98 pin */
+ {
+ trigger = default_NEC98_trigger(idx);
+ break;
+ }
default:
{
printk(KERN_WARNING "broken BIOS!!\n");
case MP_BUS_ISA: /* ISA pin */
case MP_BUS_EISA:
case MP_BUS_MCA:
+ case MP_BUS_NEC98:
{
irq = mp_irqs[idx].mpc_srcbusirq;
break;
while (i < apic)
irq += nr_ioapic_registers[i++];
irq += pin;
+
+ /*
+ * For MPS mode, so far only needed by ES7000 platform
+ */
+ if (ioapic_renumber_irq)
+ irq = ioapic_renumber_irq(apic, irq);
+
break;
}
default:
}
}
- /*
- * PCI IRQ command line redirection. Yes, limits are hardcoded.
- */
- if ((pin >= 16) && (pin <= 23)) {
- if (pirq_entries[pin-16] != -1) {
- if (!pirq_entries[pin-16]) {
- printk(KERN_DEBUG "disabling PIRQ%d\n", pin-16);
- } else {
- irq = pirq_entries[pin-16];
- printk(KERN_DEBUG "using PIRQ%d -> IRQ %d\n",
- pin-16, irq);
- }
- }
- }
return irq;
}
return 0;
}
-int irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 };
-
-int vector_irq[256];
+/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
+u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
int assign_irq_vector(int irq)
{
static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
- if (IO_APIC_VECTOR(irq) > 0)
+
+ BUG_ON(irq >= NR_IRQ_VECTORS);
+ if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
return IO_APIC_VECTOR(irq);
next:
current_vector += 8;
- /* Skip the hypercall vector. */
- if (current_vector == HYPERCALL_VECTOR) goto next;
- /* Skip the Linux/BSD fast-trap vector. */
- if (current_vector == 0x80) goto next;
+ /* Skip the hypercall vector. */
+ if (current_vector == HYPERCALL_VECTOR)
+ goto next;
+
+ /* Skip the Linux/BSD fast-trap vector. */
+ if (current_vector == 0x80)
+ goto next;
- if (current_vector > FIRST_SYSTEM_VECTOR) {
+ if (current_vector >= FIRST_SYSTEM_VECTOR) {
offset++;
+ if (!(offset%8))
+ return -ENOSPC;
current_vector = FIRST_DEVICE_VECTOR + offset;
}
- if (current_vector == FIRST_SYSTEM_VECTOR)
- panic("ran out of interrupt sources!");
-
- IO_APIC_VECTOR(irq) = current_vector;
-
- vector_irq[current_vector] = irq;
+ vector_irq[current_vector] = irq;
+ if (irq != AUTO_ASSIGN)
+ IO_APIC_VECTOR(irq) = current_vector;
return current_vector;
}
-extern void (*interrupt[NR_IRQS])(void);
+static struct hw_interrupt_type ioapic_level_type;
+static struct hw_interrupt_type ioapic_edge_type;
-/*
- * Level and edge triggered IO-APIC interrupts need different handling,
- * so we use two separate IRQ descriptors. Edge triggered IRQs can be
- * handled with the level-triggered descriptor, but that one has slightly
- * more overhead. Level-triggered interrupts cannot be handled with the
- * edge-triggered handler, without risking IRQ storms and other ugly
- * races.
- */
+#define IOAPIC_AUTO -1
+#define IOAPIC_EDGE 0
+#define IOAPIC_LEVEL 1
-static unsigned int startup_edge_ioapic_irq(unsigned int irq);
-#define shutdown_edge_ioapic_irq disable_edge_ioapic_irq
-#define enable_edge_ioapic_irq unmask_IO_APIC_irq
-static void disable_edge_ioapic_irq (unsigned int irq);
-static void ack_edge_ioapic_irq(unsigned int irq);
-static void end_edge_ioapic_irq (unsigned int i);
-static struct hw_interrupt_type ioapic_edge_irq_type = {
- "IO-APIC-edge",
- startup_edge_ioapic_irq,
- shutdown_edge_ioapic_irq,
- enable_edge_ioapic_irq,
- disable_edge_ioapic_irq,
- ack_edge_ioapic_irq,
- end_edge_ioapic_irq,
- set_ioapic_affinity,
-};
-
-static unsigned int startup_level_ioapic_irq (unsigned int irq);
-#define shutdown_level_ioapic_irq mask_IO_APIC_irq
-#define enable_level_ioapic_irq unmask_IO_APIC_irq
-#define disable_level_ioapic_irq mask_IO_APIC_irq
-static void mask_and_ack_level_ioapic_irq (unsigned int irq);
-static void end_level_ioapic_irq (unsigned int irq);
-static struct hw_interrupt_type ioapic_level_irq_type = {
- "IO-APIC-level",
- startup_level_ioapic_irq,
- shutdown_level_ioapic_irq,
- enable_level_ioapic_irq,
- disable_level_ioapic_irq,
- mask_and_ack_level_ioapic_irq,
- end_level_ioapic_irq,
- set_ioapic_affinity,
-};
+static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger)
+{
+ if (use_pci_vector() && !platform_legacy_irq(irq)) {
+ if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+ trigger == IOAPIC_LEVEL)
+ irq_desc[vector].handler = &ioapic_level_type;
+ else
+ irq_desc[vector].handler = &ioapic_edge_type;
+ set_intr_gate(vector, interrupt[vector]);
+ } else {
+ if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+ trigger == IOAPIC_LEVEL)
+ irq_desc[irq].handler = &ioapic_level_type;
+ else
+ irq_desc[irq].handler = &ioapic_edge_type;
+ set_intr_gate(vector, interrupt[irq]);
+ }
+}
void __init setup_IO_APIC_irqs(void)
{
struct IO_APIC_route_entry entry;
- int apic, pin, idx, irq, vector;
+ int apic, pin, idx, irq, first_notcon = 1, vector;
unsigned long flags;
- printk(KERN_DEBUG "init IO_APIC IRQs\n");
+ apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
for (apic = 0; apic < nr_ioapics; apic++) {
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
memset(&entry,0,sizeof(entry));
entry.delivery_mode = INT_DELIVERY_MODE;
- entry.dest_mode = (INT_DEST_ADDR_MODE != 0);
+ entry.dest_mode = INT_DEST_MODE;
entry.mask = 0; /* enable IRQ */
- entry.dest.logical.logical_dest = target_cpus();
+ entry.dest.logical.logical_dest =
+ cpu_mask_to_apicid(TARGET_CPUS);
idx = find_irq_entry(apic,pin,mp_INT);
- if (idx == -1)
+ if (idx == -1) {
+ if (first_notcon) {
+ apic_printk(APIC_VERBOSE, KERN_DEBUG
+ " IO-APIC (apicid-pin) %d-%d",
+ mp_ioapics[apic].mpc_apicid,
+ pin);
+ first_notcon = 0;
+ } else
+ apic_printk(APIC_VERBOSE, ", %d-%d",
+ mp_ioapics[apic].mpc_apicid, pin);
continue;
+ }
entry.trigger = irq_trigger(idx);
entry.polarity = irq_polarity(idx);
* skip adding the timer int on secondary nodes, which causes
* a small but painful rift in the time-space continuum
*/
- if ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)
- && (apic != 0) && (irq == 0))
+ if (multi_timer_check(apic, irq))
continue;
else
add_pin_to_irq(irq, apic, pin);
if (IO_APIC_IRQ(irq)) {
vector = assign_irq_vector(irq);
entry.vector = vector;
-
- if (IO_APIC_irq_trigger(irq))
- irq_desc[irq].handler = &ioapic_level_irq_type;
- else
- irq_desc[irq].handler = &ioapic_edge_irq_type;
-
- set_intr_gate(vector, interrupt[irq]);
+ ioapic_register_intr(irq, vector, IOAPIC_AUTO);
if (!apic && (irq < 16))
disable_8259A_irq(irq);
spin_unlock_irqrestore(&ioapic_lock, flags);
}
}
+
+ if (!first_notcon)
+ apic_printk(APIC_VERBOSE, " not connected.\n");
}
/*
- * Set up the 8259A-master output pin as broadcast to all
- * CPUs.
+ * Set up the 8259A-master output pin:
*/
void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
{
* We use logical delivery to get the timer IRQ
* to the first CPU.
*/
- entry.dest_mode = (INT_DEST_ADDR_MODE != 0);
+ entry.dest_mode = INT_DEST_MODE;
entry.mask = 0; /* unmask IRQ now */
- entry.dest.logical.logical_dest = target_cpus();
+ entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
entry.delivery_mode = INT_DELIVERY_MODE;
entry.polarity = 0;
entry.trigger = 0;
* The timer IRQ doesn't have to know that behind the
* scene we have a 8259A-master in AEOI mode ...
*/
- irq_desc[0].handler = &ioapic_edge_irq_type;
+ irq_desc[0].handler = &ioapic_edge_type;
/*
* Add it to the IO-APIC irq-routing table:
enable_8259A_irq(0);
}
-void __init UNEXPECTED_IO_APIC(void)
+static inline void UNEXPECTED_IO_APIC(void)
{
- printk(KERN_WARNING
- "An unexpected IO-APIC was found. If this kernel release is less than\n"
- "three months old please report this to linux-smp@vger.kernel.org\n");
}
void __init print_IO_APIC(void)
{
-#ifdef VERBOSE
+#ifndef NDEBUG
int apic, i;
- struct IO_APIC_reg_00 reg_00;
- struct IO_APIC_reg_01 reg_01;
- struct IO_APIC_reg_02 reg_02;
- struct IO_APIC_reg_03 reg_03;
+ union IO_APIC_reg_00 reg_00;
+ union IO_APIC_reg_01 reg_01;
+ union IO_APIC_reg_02 reg_02;
+ union IO_APIC_reg_03 reg_03;
unsigned long flags;
+ if (apic_verbosity == APIC_QUIET)
+ return;
+
printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
for (i = 0; i < nr_ioapics; i++)
printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
for (apic = 0; apic < nr_ioapics; apic++) {
spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)®_00 = io_apic_read(apic, 0);
- *(int *)®_01 = io_apic_read(apic, 1);
- if (reg_01.version >= 0x10)
- *(int *)®_02 = io_apic_read(apic, 2);
- if (reg_01.version >= 0x20)
- *(int *)®_03 = io_apic_read(apic, 3);
+ reg_00.raw = io_apic_read(apic, 0);
+ reg_01.raw = io_apic_read(apic, 1);
+ if (reg_01.bits.version >= 0x10)
+ reg_02.raw = io_apic_read(apic, 2);
+ if (reg_01.bits.version >= 0x20)
+ reg_03.raw = io_apic_read(apic, 3);
spin_unlock_irqrestore(&ioapic_lock, flags);
- printk("\n");
printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
- printk(KERN_DEBUG ".... register #00: %08X\n", *(int *)®_00);
- printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.ID);
- printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.delivery_type);
- printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.LTS);
- if (reg_00.__reserved_0 || reg_00.__reserved_1 || reg_00.__reserved_2)
+ printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+ printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID);
+ printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type);
+ printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.bits.LTS);
+ if (reg_00.bits.ID >= get_physical_broadcast())
+ UNEXPECTED_IO_APIC();
+ if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)
UNEXPECTED_IO_APIC();
- printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)®_01);
- printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.entries);
- if ( (reg_01.entries != 0x0f) && /* older (Neptune) boards */
- (reg_01.entries != 0x17) && /* typical ISA+PCI boards */
- (reg_01.entries != 0x1b) && /* Compaq Proliant boards */
- (reg_01.entries != 0x1f) && /* dual Xeon boards */
- (reg_01.entries != 0x22) && /* bigger Xeon boards */
- (reg_01.entries != 0x2E) &&
- (reg_01.entries != 0x3F)
+ printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw);
+ printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.bits.entries);
+ if ( (reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */
+ (reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */
+ (reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */
+ (reg_01.bits.entries != 0x1f) && /* dual Xeon boards */
+ (reg_01.bits.entries != 0x22) && /* bigger Xeon boards */
+ (reg_01.bits.entries != 0x2E) &&
+ (reg_01.bits.entries != 0x3F)
)
UNEXPECTED_IO_APIC();
- printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.PRQ);
- printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.version);
- if ( (reg_01.version != 0x01) && /* 82489DX IO-APICs */
- (reg_01.version != 0x02) && /* VIA */
- (reg_01.version != 0x03) && /* later VIA */
- (reg_01.version != 0x10) && /* oldest IO-APICs */
- (reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */
- (reg_01.version != 0x13) && /* Xeon IO-APICs */
- (reg_01.version != 0x20) /* Intel P64H (82806 AA) */
+ printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.bits.PRQ);
+ printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.bits.version);
+ if ( (reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */
+ (reg_01.bits.version != 0x10) && /* oldest IO-APICs */
+ (reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */
+ (reg_01.bits.version != 0x13) && /* Xeon IO-APICs */
+ (reg_01.bits.version != 0x20) /* Intel P64H (82806 AA) */
)
UNEXPECTED_IO_APIC();
- if (reg_01.__reserved_1 || reg_01.__reserved_2)
+ if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2)
UNEXPECTED_IO_APIC();
/*
* but the value of reg_02 is read as the previous read register
* value, so ignore it if reg_02 == reg_01.
*/
- if (reg_01.version >= 0x10 && *(int *)®_02 != *(int *)®_01) {
- printk(KERN_DEBUG ".... register #02: %08X\n", *(int *)®_02);
- printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.arbitration);
- if (reg_02.__reserved_1 || reg_02.__reserved_2)
+ if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
+ printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
+ printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.bits.arbitration);
+ if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2)
UNEXPECTED_IO_APIC();
}
* or reg_03, but the value of reg_0[23] is read as the previous read
* register value, so ignore it if reg_03 == reg_0[12].
*/
- if (reg_01.version >= 0x20 && *(int *)®_03 != *(int *)®_02 &&
- *(int *)®_03 != *(int *)®_01) {
- printk(KERN_DEBUG ".... register #03: %08X\n", *(int *)®_03);
- printk(KERN_DEBUG "....... : Boot DT : %X\n", reg_03.boot_DT);
- if (reg_03.__reserved_1)
+ if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&
+ reg_03.raw != reg_01.raw) {
+ printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
+ printk(KERN_DEBUG "....... : Boot DT : %X\n", reg_03.bits.boot_DT);
+ if (reg_03.bits.__reserved_1)
UNEXPECTED_IO_APIC();
}
printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
" Stat Dest Deli Vect: \n");
- for (i = 0; i <= reg_01.entries; i++) {
+ for (i = 0; i <= reg_01.bits.entries; i++) {
struct IO_APIC_route_entry entry;
spin_lock_irqsave(&ioapic_lock, flags);
);
}
}
+ if (use_pci_vector())
+ printk(KERN_INFO "Using vector-based indexing\n");
printk(KERN_DEBUG "IRQ to pin mappings:\n");
for (i = 0; i < NR_IRQS; i++) {
struct irq_pin_list *entry = irq_2_pin + i;
if (entry->pin < 0)
continue;
- printk(KERN_DEBUG "IRQ%d ", i);
+ if (use_pci_vector() && !platform_legacy_irq(i))
+ printk(KERN_DEBUG "IRQ%d ", IO_APIC_VECTOR(i));
+ else
+ printk(KERN_DEBUG "IRQ%d ", i);
for (;;) {
printk("-> %d:%d", entry->apic, entry->pin);
if (!entry->next)
}
printk(KERN_INFO ".................................... done.\n");
-#endif
-}
-
-
-#if 0 /* Maybe useful for debugging, but not currently used anywhere. */
-
-static void print_APIC_bitfield (int base)
-{
- unsigned int v;
- int i, j;
-
- printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
- for (i = 0; i < 8; i++) {
- v = apic_read(base + i*0x10);
- for (j = 0; j < 32; j++) {
- if (v & (1<<j))
- printk("1");
- else
- printk("0");
- }
- printk("\n");
- }
+#endif /* !NDEBUG */
+ return;
}
-
-void /*__init*/ print_local_APIC(void * dummy)
-{
- unsigned int v, ver, maxlvt;
-
- printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
- smp_processor_id(), hard_smp_processor_id());
- v = apic_read(APIC_ID);
- printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(v));
- v = apic_read(APIC_LVR);
- printk(KERN_INFO "... APIC VERSION: %08x\n", v);
- ver = GET_APIC_VERSION(v);
- maxlvt = get_maxlvt();
-
- v = apic_read(APIC_TASKPRI);
- printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
-
- if (APIC_INTEGRATED(ver)) { /* !82489DX */
- v = apic_read(APIC_ARBPRI);
- printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
- v & APIC_ARBPRI_MASK);
- v = apic_read(APIC_PROCPRI);
- printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
- }
-
- v = apic_read(APIC_EOI);
- printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
- v = apic_read(APIC_RRR);
- printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
- v = apic_read(APIC_LDR);
- printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
- v = apic_read(APIC_DFR);
- printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
- v = apic_read(APIC_SPIV);
- printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
-
- printk(KERN_DEBUG "... APIC ISR field:\n");
- print_APIC_bitfield(APIC_ISR);
- printk(KERN_DEBUG "... APIC TMR field:\n");
- print_APIC_bitfield(APIC_TMR);
- printk(KERN_DEBUG "... APIC IRR field:\n");
- print_APIC_bitfield(APIC_IRR);
-
- if (APIC_INTEGRATED(ver)) { /* !82489DX */
- if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
- apic_write(APIC_ESR, 0);
- v = apic_read(APIC_ESR);
- printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
- }
-
- v = apic_read(APIC_ICR);
- printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
- v = apic_read(APIC_ICR2);
- printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);
-
- v = apic_read(APIC_LVTT);
- printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
-
- if (maxlvt > 3) { /* PC is LVT#4. */
- v = apic_read(APIC_LVTPC);
- printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);
- }
- v = apic_read(APIC_LVT0);
- printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);
- v = apic_read(APIC_LVT1);
- printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);
-
- if (maxlvt > 2) { /* ERR is LVT#3. */
- v = apic_read(APIC_LVTERR);
- printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);
- }
-
- v = apic_read(APIC_TMICT);
- printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);
- v = apic_read(APIC_TMCCT);
- printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
- v = apic_read(APIC_TDCR);
- printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
- printk("\n");
-}
-
-void print_all_local_APICs (void)
-{
- smp_call_function(print_local_APIC, NULL, 1, 1);
- print_local_APIC(NULL);
-}
-
-void /*__init*/ print_PIC(void)
-{
- extern spinlock_t i8259A_lock;
- unsigned int v, flags;
-
- printk(KERN_DEBUG "\nprinting PIC contents\n");
-
- spin_lock_irqsave(&i8259A_lock, flags);
-
- v = inb(0xa1) << 8 | inb(0x21);
- printk(KERN_DEBUG "... PIC IMR: %04x\n", v);
-
- v = inb(0xa0) << 8 | inb(0x20);
- printk(KERN_DEBUG "... PIC IRR: %04x\n", v);
-
- outb(0x0b,0xa0);
- outb(0x0b,0x20);
- v = inb(0xa0) << 8 | inb(0x20);
- outb(0x0a,0xa0);
- outb(0x0a,0x20);
-
- spin_unlock_irqrestore(&i8259A_lock, flags);
-
- printk(KERN_DEBUG "... PIC ISR: %04x\n", v);
-
- v = inb(0x4d1) << 8 | inb(0x4d0);
- printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
-}
-
-#endif /* 0 */
-
-
static void __init enable_IO_APIC(void)
{
- struct IO_APIC_reg_01 reg_01;
+ union IO_APIC_reg_01 reg_01;
int i;
unsigned long flags;
irq_2_pin[i].pin = -1;
irq_2_pin[i].next = 0;
}
- if (!pirqs_enabled)
- for (i = 0; i < MAX_PIRQS; i++)
- pirq_entries[i] = -1;
/*
* The number of IO-APIC IRQ registers (== #pins):
*/
for (i = 0; i < nr_ioapics; i++) {
spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)®_01 = io_apic_read(i, 1);
+ reg_01.raw = io_apic_read(i, 1);
spin_unlock_irqrestore(&ioapic_lock, flags);
- nr_ioapic_registers[i] = reg_01.entries+1;
+ nr_ioapic_registers[i] = reg_01.bits.entries+1;
}
/*
* by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999
*/
-static void __init setup_ioapic_ids_from_mpc (void)
+#ifndef CONFIG_X86_NUMAQ
+static void __init setup_ioapic_ids_from_mpc(void)
{
- struct IO_APIC_reg_00 reg_00;
- unsigned long phys_id_present_map = phys_cpu_present_map;
+ union IO_APIC_reg_00 reg_00;
+ physid_mask_t phys_id_present_map;
int apic;
int i;
unsigned char old_id;
unsigned long flags;
- if (clustered_apic_mode)
- /* We don't have a good way to do this yet - hack */
- phys_id_present_map = (u_long) 0xf;
+ /*
+ * This is broken; anything with a real cpu count has to
+ * circumvent this idiocy regardless.
+ */
+ phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map);
+
/*
* Set the IOAPIC ID to the value stored in the MPC table.
*/
/* Read the register 0 value */
spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)®_00 = io_apic_read(apic, 0);
+ reg_00.raw = io_apic_read(apic, 0);
spin_unlock_irqrestore(&ioapic_lock, flags);
old_id = mp_ioapics[apic].mpc_apicid;
- if (mp_ioapics[apic].mpc_apicid >= apic_broadcast_id) {
+ if (mp_ioapics[apic].mpc_apicid >= get_physical_broadcast()) {
printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
apic, mp_ioapics[apic].mpc_apicid);
printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
- reg_00.ID);
- mp_ioapics[apic].mpc_apicid = reg_00.ID;
+ reg_00.bits.ID);
+ mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
}
+ /* Don't check I/O APIC IDs for some xAPIC systems. They have
+ * no meaning without the serial APIC bus. */
+ if (NO_IOAPIC_CHECK)
+ continue;
/*
* Sanity check, is the ID really free? Every APIC in a
* system must have a unique ID or we get lots of nice
* 'stuck on smp_invalidate_needed IPI wait' messages.
- * I/O APIC IDs no longer have any meaning for xAPICs and SAPICs.
*/
- if ((clustered_apic_mode != CLUSTERED_APIC_XAPIC) &&
- (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid))) {
+ if (check_apicid_used(phys_id_present_map,
+ mp_ioapics[apic].mpc_apicid)) {
printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
apic, mp_ioapics[apic].mpc_apicid);
- for (i = 0; i < 0xf; i++)
- if (!(phys_id_present_map & (1 << i)))
+ for (i = 0; i < get_physical_broadcast(); i++)
+ if (!physid_isset(i, phys_id_present_map))
break;
- if (i >= apic_broadcast_id)
+ if (i >= get_physical_broadcast())
panic("Max APIC ID exceeded!\n");
printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
i);
- phys_id_present_map |= 1 << i;
+ physid_set(i, phys_id_present_map);
mp_ioapics[apic].mpc_apicid = i;
} else {
- printk("Setting %d in the phys_id_present_map\n", mp_ioapics[apic].mpc_apicid);
- phys_id_present_map |= 1 << mp_ioapics[apic].mpc_apicid;
+ physid_mask_t tmp;
+ tmp = apicid_to_cpu_present(mp_ioapics[apic].mpc_apicid);
+ apic_printk(APIC_VERBOSE, "Setting %d in the "
+ "phys_id_present_map\n",
+ mp_ioapics[apic].mpc_apicid);
+ physids_or(phys_id_present_map, phys_id_present_map, tmp);
}
* Read the right value from the MPC table and
* write it into the ID register.
*/
- printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
- mp_ioapics[apic].mpc_apicid);
+ apic_printk(APIC_VERBOSE, KERN_INFO
+ "...changing IO-APIC physical APIC ID to %d ...",
+ mp_ioapics[apic].mpc_apicid);
- reg_00.ID = mp_ioapics[apic].mpc_apicid;
+ reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic, 0, *(int *)®_00);
+ io_apic_write(apic, 0, reg_00.raw);
spin_unlock_irqrestore(&ioapic_lock, flags);
/*
* Sanity check
*/
spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)®_00 = io_apic_read(apic, 0);
+ reg_00.raw = io_apic_read(apic, 0);
spin_unlock_irqrestore(&ioapic_lock, flags);
- if (reg_00.ID != mp_ioapics[apic].mpc_apicid)
- panic("could not set ID!\n");
+ if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
+ printk("could not set ID!\n");
else
- printk(" ok.\n");
+ apic_printk(APIC_VERBOSE, " ok.\n");
}
}
+#else
+static void __init setup_ioapic_ids_from_mpc(void) { }
+#endif
/*
* There is a nasty bug in some older SMP boards, their mptable lies
*/
static int __init timer_irq_works(void)
{
- unsigned int t1 = jiffies;
+ unsigned long t1 = jiffies;
- __sti();
+ local_irq_enable();
/* Let ten ticks pass... */
mdelay((10 * 1000) / HZ);
return 0;
}
-static void disable_edge_ioapic_irq (unsigned int irq) { /* nothing */ }
+/*
+ * In the SMP+IOAPIC case it might happen that there are an unspecified
+ * number of pending IRQ events unhandled. These cases are very rare,
+ * so we 'resend' these IRQs via IPIs, to the same CPU. It's much
+ * better to do it this way as thus we do not have to be aware of
+ * 'pending' interrupts in the IRQ path, except at this point.
+ */
+/*
+ * Edge triggered needs to resend any interrupt
+ * that was delayed but this is now handled in the device
+ * independent code.
+ */
/*
* Starting up a edge-triggered IO-APIC interrupt is
* This is not complete - we should be able to fake
* an edge even if it isn't on the 8259A...
*/
-
static unsigned int startup_edge_ioapic_irq(unsigned int irq)
{
int was_pending = 0;
*/
static void ack_edge_ioapic_irq(unsigned int irq)
{
- balance_irq(irq);
+ move_irq(irq);
if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
== (IRQ_PENDING | IRQ_DISABLED))
mask_IO_APIC_irq(irq);
ack_APIC_irq();
}
-static void end_edge_ioapic_irq (unsigned int i) { /* nothing */ }
-
-
/*
* Level triggered interrupts can just be masked,
* and shutting down and starting up the interrupt
return 0; /* don't check for pending */
}
-static void mask_and_ack_level_ioapic_irq(unsigned int irq)
+static void end_level_ioapic_irq (unsigned int irq)
{
unsigned long v;
int i;
- balance_irq(irq);
-
- mask_IO_APIC_irq(irq);
-
+ move_irq(irq);
/*
* It appears there is an erratum which affects at least version 0x11
* of I/O APIC (that's the 82093AA and cores integrated into various
* The idea is from Manfred Spraul. --macro
*/
i = IO_APIC_VECTOR(irq);
+
v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
ack_APIC_irq();
if (!(v & (1 << (i & 0x1f)))) {
-#ifdef APIC_LOCKUP_DEBUG
- struct irq_pin_list *entry;
-#endif
-
-#ifdef APIC_MISMATCH_DEBUG
atomic_inc(&irq_mis_count);
-#endif
spin_lock(&ioapic_lock);
- __edge_IO_APIC_irq(irq);
-#ifdef APIC_LOCKUP_DEBUG
- for (entry = irq_2_pin + irq;;) {
- unsigned int reg;
-
- if (entry->pin == -1)
- break;
- reg = io_apic_read(entry->apic, 0x10 + entry->pin * 2);
- if (reg & 0x00004000)
- printk(KERN_CRIT "Aieee!!! Remote IRR"
- " still set after unlock!\n");
- if (!entry->next)
- break;
- entry = irq_2_pin + entry->next;
- }
-#endif
- __level_IO_APIC_irq(irq);
+ __mask_and_edge_IO_APIC_irq(irq);
+ __unmask_and_level_IO_APIC_irq(irq);
spin_unlock(&ioapic_lock);
}
}
-static void end_level_ioapic_irq(unsigned int irq)
+#ifdef CONFIG_PCI_MSI
+static unsigned int startup_edge_ioapic_vector(unsigned int vector)
+{
+ int irq = vector_to_irq(vector);
+
+ return startup_edge_ioapic_irq(irq);
+}
+
+static void ack_edge_ioapic_vector(unsigned int vector)
+{
+ int irq = vector_to_irq(vector);
+
+ ack_edge_ioapic_irq(irq);
+}
+
+static unsigned int startup_level_ioapic_vector (unsigned int vector)
+{
+ int irq = vector_to_irq(vector);
+
+ return startup_level_ioapic_irq (irq);
+}
+
+static void end_level_ioapic_vector (unsigned int vector)
+{
+ int irq = vector_to_irq(vector);
+
+ end_level_ioapic_irq(irq);
+}
+
+static void mask_IO_APIC_vector (unsigned int vector)
{
+ int irq = vector_to_irq(vector);
+
+ mask_IO_APIC_irq(irq);
+}
+
+static void unmask_IO_APIC_vector (unsigned int vector)
+{
+ int irq = vector_to_irq(vector);
+
unmask_IO_APIC_irq(irq);
}
+static void set_ioapic_affinity_vector (unsigned int vector,
+ cpumask_t cpu_mask)
+{
+ int irq = vector_to_irq(vector);
+
+ set_ioapic_affinity_irq(irq, cpu_mask);
+}
+#endif
+
+/*
+ * Level and edge triggered IO-APIC interrupts need different handling,
+ * so we use two separate IRQ descriptors. Edge triggered IRQs can be
+ * handled with the level-triggered descriptor, but that one has slightly
+ * more overhead. Level-triggered interrupts cannot be handled with the
+ * edge-triggered handler, without risking IRQ storms and other ugly
+ * races.
+ */
+static struct hw_interrupt_type ioapic_edge_type = {
+ .typename = "IO-APIC-edge",
+ .startup = startup_edge_ioapic,
+ .shutdown = shutdown_edge_ioapic,
+ .enable = enable_edge_ioapic,
+ .disable = disable_edge_ioapic,
+ .ack = ack_edge_ioapic,
+ .end = end_edge_ioapic,
+ .set_affinity = set_ioapic_affinity,
+};
+
+static struct hw_interrupt_type ioapic_level_type = {
+ .typename = "IO-APIC-level",
+ .startup = startup_level_ioapic,
+ .shutdown = shutdown_level_ioapic,
+ .enable = enable_level_ioapic,
+ .disable = disable_level_ioapic,
+ .ack = mask_and_ack_level_ioapic,
+ .end = end_level_ioapic,
+ .set_affinity = set_ioapic_affinity,
+};
+
static inline void init_IO_APIC_traps(void)
{
int irq;
* 0x80, because int 0x80 is hm, kind of importantish. ;)
*/
for (irq = 0; irq < NR_IRQS ; irq++) {
- if (IO_APIC_IRQ(irq) && !IO_APIC_VECTOR(irq)) {
+ int tmp = irq;
+ if (use_pci_vector()) {
+ if (!platform_legacy_irq(tmp))
+ if ((tmp = vector_to_irq(tmp)) == -1)
+ continue;
+ }
+ if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) {
/*
* Hmm.. We don't have an entry for this,
* so default to an old-fashioned 8259
static void end_lapic_irq (unsigned int i) { /* nothing */ }
static struct hw_interrupt_type lapic_irq_type = {
- "local-APIC-edge",
- NULL, /* startup_irq() not used for IRQ0 */
- NULL, /* shutdown_irq() not used for IRQ0 */
- enable_lapic_irq,
- disable_lapic_irq,
- ack_lapic_irq,
- end_lapic_irq
+ .typename = "local-APIC-edge",
+ .startup = NULL, /* startup_irq() not used for IRQ0 */
+ .shutdown = NULL, /* shutdown_irq() not used for IRQ0 */
+ .enable = enable_lapic_irq,
+ .disable = disable_lapic_irq,
+ .ack = ack_lapic_irq,
+ .end = end_lapic_irq
};
+#if 0
+static void setup_nmi (void)
+{
+ /*
+ * Dirty trick to enable the NMI watchdog ...
+ * We put the 8259A master into AEOI mode and
+ * unmask on all local APICs LVT0 as NMI.
+ *
+ * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
+ * is from Maciej W. Rozycki - so we do not have to EOI from
+ * the NMI handler or the timer interrupt.
+ */
+ apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
+
+ on_each_cpu(enable_NMI_through_LVT0, NULL, 1, 1);
+
+ apic_printk(APIC_VERBOSE, " done.\n");
+}
+#endif
+
/*
* This looks a bit hackish but it's about the only one way of sending
* a few INTA cycles to 8259As and any associated glue logic. ICR does
*/
static inline void check_timer(void)
{
- extern int timer_ack;
int pin1, pin2;
int vector;
* Ok, does IRQ0 through the IOAPIC work?
*/
unmask_IO_APIC_irq(0);
- if (timer_irq_works())
+ if (timer_irq_works()) {
+#if 0
+ if (nmi_watchdog == NMI_IO_APIC) {
+ disable_8259A_irq(0);
+ setup_nmi();
+ enable_8259A_irq(0);
+ check_nmi_watchdog();
+ }
+#endif
return;
+ }
clear_IO_APIC_pin(0, pin1);
printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
}
replace_pin_at_irq(0, 0, pin1, 0, pin2);
else
add_pin_to_irq(0, 0, pin2);
+#if 0
+ if (nmi_watchdog == NMI_IO_APIC) {
+ setup_nmi();
+ check_nmi_watchdog();
+ }
+#endif
return;
}
/*
}
printk(" failed.\n");
+ if (nmi_watchdog == NMI_IO_APIC) {
+ printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
+ nmi_watchdog = 0;
+ }
+
printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
disable_8259A_irq(0);
printk(KERN_INFO "...trying to set up timer as ExtINT IRQ...");
+ timer_ack = 0;
init_8259A(0);
make_8259A_irq(0);
apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
return;
}
printk(" failed :(.\n");
- panic("IO-APIC + timer doesn't work! pester mingo@redhat.com");
+ panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a "
+ "report. Then try booting with the 'noapic' option");
}
#define NR_IOAPIC_BIOSIDS 256
/*
*
- * IRQ's that are handled by the old PIC in all cases:
+ * IRQ's that are handled by the PIC in the MPS IOAPIC case.
* - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
* Linux doesn't really care, as it's not actually used
* for any interrupt handling anyway.
- * - There used to be IRQ13 here as well, but all
- * MPS-compliant must not use it for FPU coupling and we
- * want to use exception 16 anyway. And there are
- * systems who connect it to an I/O APIC for other uses.
- * Thus we don't mark it special any longer.
- *
- * Additionally, something is definitely wrong with irq9
- * on PIIX4 boards.
*/
-#define PIC_IRQS (1<<2)
+#define PIC_IRQS (1 << PIC_CASCADE_IR)
void __init setup_IO_APIC(void)
{
enable_IO_APIC();
- io_apic_irqs = ~PIC_IRQS;
+ if (acpi_ioapic)
+ io_apic_irqs = ~0; /* all IRQs go through IOAPIC */
+ else
+ io_apic_irqs = ~PIC_IRQS;
+
printk("ENABLING IO-APIC IRQs\n");
/*
print_IO_APIC();
}
-#endif /* CONFIG_X86_IO_APIC */
-
-
-
/* --------------------------------------------------------------------------
ACPI-based IOAPIC Configuration
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_BOOT
-#define IO_APIC_MAX_ID 15
-
int __init io_apic_get_unique_id (int ioapic, int apic_id)
{
- struct IO_APIC_reg_00 reg_00;
- static unsigned long apic_id_map = 0;
+ union IO_APIC_reg_00 reg_00;
+ static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
+ physid_mask_t tmp;
unsigned long flags;
int i = 0;
* advantage of new APIC bus architecture.
*/
- if (!apic_id_map)
- apic_id_map = phys_cpu_present_map;
+ if (physids_empty(apic_id_map))
+ apic_id_map = ioapic_phys_id_map(phys_cpu_present_map);
spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)®_00 = io_apic_read(ioapic, 0);
+ reg_00.raw = io_apic_read(ioapic, 0);
spin_unlock_irqrestore(&ioapic_lock, flags);
- if (apic_id >= IO_APIC_MAX_ID) {
+ if (apic_id >= get_physical_broadcast()) {
printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
- "%d\n", ioapic, apic_id, reg_00.ID);
- apic_id = reg_00.ID;
- }
-
- /* XAPICs do not need unique IDs */
- if (clustered_apic_mode == CLUSTERED_APIC_XAPIC){
- printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n",
- ioapic, apic_id);
- return apic_id;
+ "%d\n", ioapic, apic_id, reg_00.bits.ID);
+ apic_id = reg_00.bits.ID;
}
/*
* Every APIC in a system must have a unique ID or we get lots of nice
* 'stuck on smp_invalidate_needed IPI wait' messages.
*/
- if (apic_id_map & (1 << apic_id)) {
+ if (check_apicid_used(apic_id_map, apic_id)) {
- for (i = 0; i < IO_APIC_MAX_ID; i++) {
- if (!(apic_id_map & (1 << i)))
+ for (i = 0; i < get_physical_broadcast(); i++) {
+ if (!check_apicid_used(apic_id_map, i))
break;
}
- if (i == IO_APIC_MAX_ID)
+ if (i == get_physical_broadcast())
panic("Max apic_id exceeded!\n");
printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
apic_id = i;
}
- apic_id_map |= (1 << apic_id);
+ tmp = apicid_to_cpu_present(apic_id);
+ physids_or(apic_id_map, apic_id_map, tmp);
- if (reg_00.ID != apic_id) {
- reg_00.ID = apic_id;
+ if (reg_00.bits.ID != apic_id) {
+ reg_00.bits.ID = apic_id;
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(ioapic, 0, *(int *)®_00);
- *(int *)®_00 = io_apic_read(ioapic, 0);
+ io_apic_write(ioapic, 0, reg_00.raw);
+ reg_00.raw = io_apic_read(ioapic, 0);
spin_unlock_irqrestore(&ioapic_lock, flags);
/* Sanity check */
- if (reg_00.ID != apic_id)
+ if (reg_00.bits.ID != apic_id)
panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
}
- printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
+ apic_printk(APIC_VERBOSE, KERN_INFO
+ "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
return apic_id;
}
int __init io_apic_get_version (int ioapic)
{
- struct IO_APIC_reg_01 reg_01;
+ union IO_APIC_reg_01 reg_01;
unsigned long flags;
spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)®_01 = io_apic_read(ioapic, 1);
+ reg_01.raw = io_apic_read(ioapic, 1);
spin_unlock_irqrestore(&ioapic_lock, flags);
- return reg_01.version;
+ return reg_01.bits.version;
}
int __init io_apic_get_redir_entries (int ioapic)
{
- struct IO_APIC_reg_01 reg_01;
+ union IO_APIC_reg_01 reg_01;
unsigned long flags;
spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)®_01 = io_apic_read(ioapic, 1);
+ reg_01.raw = io_apic_read(ioapic, 1);
spin_unlock_irqrestore(&ioapic_lock, flags);
- return reg_01.entries;
+ return reg_01.bits.entries;
}
unsigned long flags;
if (!IO_APIC_IRQ(irq)) {
- printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0/n",
+ printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
ioapic);
return -EINVAL;
}
memset(&entry,0,sizeof(entry));
- entry.delivery_mode = dest_LowestPrio;
- entry.dest_mode = INT_DELIVERY_MODE;
- entry.dest.logical.logical_dest = target_cpus();
- entry.mask = 1; /* Disabled (masked) */
+ entry.delivery_mode = INT_DELIVERY_MODE;
+ entry.dest_mode = INT_DEST_MODE;
+ entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
entry.trigger = edge_level;
entry.polarity = active_high_low;
+ entry.mask = 1;
/*
* IRQs < 16 are already in the irq_2_pin[] map
entry.vector = assign_irq_vector(irq);
- printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
- "IRQ %d Mode:%i Active:%i)\n", ioapic,
- mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low);
-
- if (edge_level) {
- irq_desc[irq].handler = &ioapic_level_irq_type;
- } else {
- irq_desc[irq].handler = &ioapic_edge_irq_type;
- }
+ apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry "
+ "(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic,
+ mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
+ edge_level, active_high_low);
- set_intr_gate(entry.vector, interrupt[irq]);
+ ioapic_register_intr(irq, entry.vector, edge_level);
if (!ioapic && (irq < 16))
disable_8259A_irq(irq);
#endif /*CONFIG_ACPI_BOOT*/
-/* opt_leveltrigger, opt_edgetrigger: Force an IO-APIC-routed IRQ to be */
-/* level- or edge-triggered. */
-/* Example: 'leveltrigger=4,5,6,20 edgetrigger=21'. */
-static char opt_leveltrigger[30] = "", opt_edgetrigger[30] = "";
-string_param("leveltrigger", opt_leveltrigger);
-string_param("edgetrigger", opt_edgetrigger);
-
-static int __init ioapic_trigger_setup(void)
-{
- char *p;
- irq_desc_t *desc;
- long irq;
-
- p = opt_leveltrigger;
- while ( *p != '\0' )
- {
- irq = simple_strtol(p, &p, 10);
- if ( (irq <= 0) || (irq >= NR_IRQS) )
- {
- printk("IRQ '%ld' out of range in level-trigger list '%s'\n",
- irq, opt_leveltrigger);
- break;
- }
-
- printk("Forcing IRQ %ld to level-trigger: ", irq);
-
- desc = &irq_desc[irq];
- spin_lock_irq(&desc->lock);
-
- if ( desc->handler == &ioapic_level_irq_type )
- {
- printk("already level-triggered (no force applied).\n");
- }
- else if ( desc->handler != &ioapic_edge_irq_type )
- {
- printk("cannot force (can only force IO-APIC-edge IRQs).\n");
- }
- else
- {
- desc->handler = &ioapic_level_irq_type;
- __mask_IO_APIC_irq(irq);
- __level_IO_APIC_irq(irq);
- printk("done.\n");
- }
-
- spin_unlock_irq(&desc->lock);
-
- if ( *p == '\0' )
- break;
-
- if ( *p != ',' )
- {
- printk("Unexpected character '%c' in level-trigger list '%s'\n",
- *p, opt_leveltrigger);
- break;
- }
-
- p++;
- }
-
- p = opt_edgetrigger;
- while ( *p != '\0' )
- {
- irq = simple_strtol(p, &p, 10);
- if ( (irq <= 0) || (irq >= NR_IRQS) )
- {
- printk("IRQ '%ld' out of range in edge-trigger list '%s'\n",
- irq, opt_edgetrigger);
- break;
- }
-
- printk("Forcing IRQ %ld to edge-trigger: ", irq);
-
- desc = &irq_desc[irq];
- spin_lock_irq(&desc->lock);
-
- if ( desc->handler == &ioapic_edge_irq_type )
- {
- printk("already edge-triggered (no force applied).\n");
- }
- else if ( desc->handler != &ioapic_level_irq_type )
- {
- printk("cannot force (can only force IO-APIC-level IRQs).\n");
- }
- else
- {
- desc->handler = &ioapic_edge_irq_type;
- __edge_IO_APIC_irq(irq);
- desc->status |= IRQ_PENDING; /* may have lost a masked edge */
- printk("done.\n");
- }
-
- spin_unlock_irq(&desc->lock);
-
- if ( *p == '\0' )
- break;
-
- if ( *p != ',' )
- {
- printk("Unexpected character '%c' in edge-trigger list '%s'\n",
- *p, opt_edgetrigger);
- break;
- }
-
- p++;
- }
-
- return 0;
-}
-
-__initcall(ioapic_trigger_setup);
int ioapic_guest_read(int apicid, int address, u32 *pval)
{
u32 val;
int apicenum;
- struct IO_APIC_reg_00 reg_00;
+ union IO_APIC_reg_00 reg_00;
unsigned long flags;
if ( (apicid >= NR_IOAPIC_BIOSIDS) ||
/* Rewrite APIC ID to what the BIOS originally specified. */
if ( address == 0 )
{
- *(int *)®_00 = val;
- reg_00.ID = apicid;
- val = *(u32 *)®_00;
+ reg_00.raw = val;
+ reg_00.bits.ID = apicid;
+ val = reg_00.raw;
}
*pval = val;
/* Set the correct irq-handling type. */
irq_desc[irq].handler = rte.trigger ?
- &ioapic_level_irq_type: &ioapic_edge_irq_type;
+ &ioapic_level_type: &ioapic_edge_type;
/* Record the pin<->irq mapping. */
for ( entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next] )
};
atomic_t irq_err_count;
-atomic_t irq_mis_count;
inline void disable_irq_nosync(unsigned int irq)
{
#define vmalloc(_s) xmalloc_bytes(_s)
#define vfree(_p) xfree(_p)
#define num_online_cpus() smp_num_cpus
-static inline int on_each_cpu(
- void (*func) (void *info), void *info, int retry, int wait)
-{
- int ret = smp_call_function(func, info, retry, wait);
- func(info);
- return ret;
-}
#if 0
MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
/*
- * Intel Multiprocessor Specificiation 1.1 and 1.4
+ * Intel Multiprocessor Specification 1.1 and 1.4
* compliant MP-table parsing routines.
*
* (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
*/
#include <xen/config.h>
-#include <xen/init.h>
-#include <xen/lib.h>
-#include <xen/kernel.h>
+#include <xen/types.h>
#include <xen/irq.h>
-#include <xen/smp.h>
-#include <xen/mm.h>
+#include <xen/init.h>
#include <xen/acpi.h>
+#include <xen/delay.h>
+#include <xen/sched.h>
+
+#include <asm/mc146818rtc.h>
+#include <asm/bitops.h>
+#include <asm/smp.h>
#include <asm/acpi.h>
-#include <asm/io.h>
-#include <asm/apic.h>
+#include <asm/mtrr.h>
#include <asm/mpspec.h>
-#include <asm/flushtlb.h>
-#include <asm/smpboot.h>
+#include <asm/io_apic.h>
-int numnodes = 1; /* XXX Xen */
+#include <mach_apic.h>
+#include <mach_mpparse.h>
+#include <bios_ebda.h>
+
+#define es7000_plat 0 /* XXX XEN */
/* Have we found an MP table */
int smp_found_config;
+unsigned int __initdata maxcpus = NR_CPUS;
/*
* Various Linux-internal data structures created from the
* MP-table.
*/
int apic_version [MAX_APICS];
+int mp_bus_id_to_type [MAX_MP_BUSSES];
+int mp_bus_id_to_node [MAX_MP_BUSSES];
+int mp_bus_id_to_local [MAX_MP_BUSSES];
int quad_local_to_mp_bus_id [NR_CPUS/4][4];
+int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
int mp_current_pci_id;
-int *mp_bus_id_to_type;
-int *mp_bus_id_to_node;
-int *mp_bus_id_to_local;
-int *mp_bus_id_to_pci_bus;
-int max_mp_busses;
-int max_irq_sources;
/* I/O APIC entries */
struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
/* # of MP IRQ source entries */
-struct mpc_config_intsrc *mp_irqs;
+struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* MP IRQ source entries */
int mp_irq_entries;
unsigned int boot_cpu_physical_apicid = -1U;
unsigned int boot_cpu_logical_apicid = -1U;
/* Internal processor count */
-static unsigned int num_processors;
+static unsigned int __initdata num_processors;
/* Bitmask of physically existing CPUs */
-unsigned long phys_cpu_present_map;
-unsigned long logical_cpu_present_map;
+physid_mask_t phys_cpu_present_map;
-#ifdef CONFIG_X86_CLUSTERED_APIC
-unsigned char esr_disable = 0;
-unsigned char clustered_apic_mode = CLUSTERED_APIC_NONE;
-unsigned int apic_broadcast_id = APIC_BROADCAST_ID_APIC;
-#endif
-unsigned char raw_phys_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
/*
* Intel MP BIOS table parsing routines:
*/
-#ifndef CONFIG_X86_VISWS_APIC
+
/*
* Checksum an MP configuration block.
*/
}
/*
- * Processor encoding in an MP configuration block
- */
-
-static char __init *mpc_family(int family,int model)
-{
- static char n[32];
- static char *model_defs[]=
- {
- "80486DX","80486DX",
- "80486SX","80486DX/2 or 80487",
- "80486SL","80486SX/2",
- "Unknown","80486DX/2-WB",
- "80486DX/4","80486DX/4-WB"
- };
-
- switch (family) {
- case 0x04:
- if (model < 10)
- return model_defs[model];
- break;
-
- case 0x05:
- return("Pentium(tm)");
-
- case 0x06:
- return("Pentium(tm) Pro");
-
- case 0x0F:
- if (model == 0x00)
- return("Pentium 4(tm)");
- if (model == 0x01)
- return("Pentium 4(tm)");
- if (model == 0x02)
- return("Pentium 4(tm) XEON(tm)");
- if (model == 0x0F)
- return("Special controller");
- }
- sprintf(n,"Unknown CPU [%d:%d]",family, model);
- return n;
-}
-
-/*
* Have to match translation table entries to main table entries by counter
* hence the mpc_record variable .... can't see a less disgusting way of
* doing this ....
static int mpc_record;
static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
+#ifdef CONFIG_X86_NUMAQ
+static int MP_valid_apicid(int apicid, int version)
+{
+ return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf;
+}
+#else
+static int MP_valid_apicid(int apicid, int version)
+{
+ if (version >= 0x14)
+ return apicid < 0xff;
+ else
+ return apicid < 0xf;
+}
+#endif
+
void __init MP_processor_info (struct mpc_config_processor *m)
{
- int ver, quad, logical_apicid;
+ int ver, apicid;
+ physid_mask_t tmp;
if (!(m->mpc_cpuflag & CPU_ENABLED))
return;
- logical_apicid = m->mpc_apicid;
- if (clustered_apic_mode == CLUSTERED_APIC_NUMAQ) {
- quad = translation_table[mpc_record]->trans_quad;
- logical_apicid = (quad << 4) +
- (m->mpc_apicid ? m->mpc_apicid << 1 : 1);
- printk("Processor #%d %s APIC version %d (quad %d, apic %d)\n",
- m->mpc_apicid,
- mpc_family((m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,
- (m->mpc_cpufeature & CPU_MODEL_MASK)>>4),
- m->mpc_apicver, quad, logical_apicid);
- } else {
- printk("Processor #%d %s APIC version %d\n",
- m->mpc_apicid,
- mpc_family((m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,
- (m->mpc_cpufeature & CPU_MODEL_MASK)>>4),
- m->mpc_apicver);
- }
+ apicid = mpc_apic_id(m, translation_table[mpc_record]);
if (m->mpc_featureflag&(1<<0))
Dprintk(" Floating point unit present.\n");
if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
Dprintk(" Bootup CPU\n");
boot_cpu_physical_apicid = m->mpc_apicid;
- boot_cpu_logical_apicid = logical_apicid;
+ boot_cpu_logical_apicid = apicid;
}
- if (num_processors >= NR_CPUS){
- printk(KERN_WARNING "NR_CPUS limit of %i reached. Cannot "
- "boot CPU(apicid 0x%x).\n", NR_CPUS, m->mpc_apicid);
+ if (num_processors >= NR_CPUS) {
+ printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
+ " Processor ignored.\n", NR_CPUS);
+ return;
+ }
+
+ if (num_processors >= maxcpus) {
+ printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
+ " Processor ignored.\n", maxcpus);
return;
}
num_processors++;
+ ver = m->mpc_apicver;
- if (m->mpc_apicid > MAX_APICS) {
- printk("Processor #%d INVALID. (Max ID: %d).\n",
+ if (!MP_valid_apicid(apicid, ver)) {
+ printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
m->mpc_apicid, MAX_APICS);
--num_processors;
return;
}
- ver = m->mpc_apicver;
- logical_cpu_present_map |= 1 << (num_processors-1);
- phys_cpu_present_map |= apicid_to_phys_cpu_present(m->mpc_apicid);
-
+ tmp = apicid_to_cpu_present(apicid);
+ physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
+
/*
* Validate version
*/
if (ver == 0x0) {
- printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
+ printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
ver = 0x10;
}
apic_version[m->mpc_apicid] = ver;
- raw_phys_apicid[num_processors - 1] = m->mpc_apicid;
+ bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
}
static void __init MP_bus_info (struct mpc_config_bus *m)
{
char str[7];
- int quad;
memcpy(str, m->mpc_bustype, 6);
str[6] = 0;
-
- if (clustered_apic_mode == CLUSTERED_APIC_NUMAQ) {
- quad = translation_table[mpc_record]->trans_quad;
- mp_bus_id_to_node[m->mpc_busid] = quad;
- mp_bus_id_to_local[m->mpc_busid] = translation_table[mpc_record]->trans_local;
- quad_local_to_mp_bus_id[quad][translation_table[mpc_record]->trans_local] = m->mpc_busid;
- printk("Bus #%d is %s (node %d)\n", m->mpc_busid, str, quad);
- } else {
- Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
- }
+
+ mpc_oem_bus_info(m, str, translation_table[mpc_record]);
if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
+ mpc_oem_pci_bus(m, translation_table[mpc_record]);
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
mp_current_pci_id++;
} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
+ } else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) {
+ mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98;
} else {
- printk("Unknown bustype %s - ignoring\n", str);
+ printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
}
}
if (!(m->mpc_flags & MPC_APIC_USABLE))
return;
- printk("I/O APIC #%d Version %d at 0x%X.\n",
+ printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
if (nr_ioapics >= MAX_IO_APICS) {
- printk("Max # of I/O APICs (%d) exceeded (found %d).\n",
+ printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n",
MAX_IO_APICS, nr_ioapics);
panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
}
m->mpc_irqtype, m->mpc_irqflag & 3,
(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
- if (++mp_irq_entries == max_irq_sources)
+ if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}
BUG();
}
+#ifdef CONFIG_X86_NUMAQ
static void __init MP_translation_info (struct mpc_config_translation *m)
{
- printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
+ printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
if (mpc_record >= MAX_MPC_ENTRY)
- printk("MAX_MPC_ENTRY exceeded!\n");
+ printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
else
translation_table[mpc_record] = m; /* stash this for later */
- if (m->trans_quad+1 > numnodes)
- numnodes = m->trans_quad+1;
+ if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
+ node_set_online(m->trans_quad);
}
/*
int count = sizeof (*oemtable); /* the header size */
unsigned char *oemptr = ((unsigned char *)oemtable)+count;
- printk("Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
+ mpc_record = 0;
+ printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))
{
- printk("SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
+ printk(KERN_WARNING "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
oemtable->oem_signature[0],
oemtable->oem_signature[1],
oemtable->oem_signature[2],
}
if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length))
{
- printk("SMP oem mptable: checksum error!\n");
+ printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
return;
}
while (count < oemtable->oem_length) {
}
default:
{
- printk("Unrecognised OEM table entry type! - %d\n", (int) *oemptr);
+ printk(KERN_WARNING "Unrecognised OEM table entry type! - %d\n", (int) *oemptr);
return;
}
}
}
}
+static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
+ char *productid)
+{
+ if (strncmp(oem, "IBM NUMA", 8))
+ printk("Warning! May not be a NUMA-Q system!\n");
+ if (mpc->mpc_oemptr)
+ smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr,
+ mpc->mpc_oemsize);
+}
+#endif /* CONFIG_X86_NUMAQ */
+
/*
* Read/parse the MPC
*/
static int __init smp_read_mpc(struct mp_config_table *mpc)
{
- char oem[16], prod[14];
+ char str[16];
+ char oem[10];
int count=sizeof(*mpc);
unsigned char *mpt=((unsigned char *)mpc)+count;
- int num_bus = 0;
- int num_irq = 0;
- unsigned char *bus_data;
if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
- panic("SMP mptable: bad signature [%c%c%c%c]!\n",
- mpc->mpc_signature[0],
- mpc->mpc_signature[1],
- mpc->mpc_signature[2],
- mpc->mpc_signature[3]);
+ printk(KERN_ERR "SMP mptable: bad signature [0x%x]!\n",
+ *(u32 *)mpc->mpc_signature);
return 0;
}
if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
- panic("SMP mptable: checksum error!\n");
+ printk(KERN_ERR "SMP mptable: checksum error!\n");
return 0;
}
if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
}
memcpy(oem,mpc->mpc_oem,8);
oem[8]=0;
- printk("OEM ID: %s ",oem);
+ printk(KERN_INFO "OEM ID: %s ",oem);
- memcpy(prod,mpc->mpc_productid,12);
- prod[12]=0;
- printk("Product ID: %s ",prod);
+ memcpy(str,mpc->mpc_productid,12);
+ str[12]=0;
+ printk("Product ID: %s ",str);
+
+ mps_oem_check(mpc, oem, str);
- detect_clustered_apic(oem, prod);
-
printk("APIC at: 0x%X\n",mpc->mpc_lapic);
/*
if (!acpi_lapic)
mp_lapic_addr = mpc->mpc_lapic;
- if ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ) && mpc->mpc_oemptr) {
- /* We need to process the oem mpc tables to tell us which quad things are in ... */
- mpc_record = 0;
- smp_read_mpc_oem((struct mp_config_oemtable *)(unsigned long)mpc->mpc_oemptr, mpc->mpc_oemsize);
- mpc_record = 0;
- }
-
- /* Pre-scan to determine the number of bus and
- * interrupts records we have
- */
- while (count < mpc->mpc_length) {
- switch (*mpt) {
- case MP_PROCESSOR:
- mpt += sizeof(struct mpc_config_processor);
- count += sizeof(struct mpc_config_processor);
- break;
- case MP_BUS:
- ++num_bus;
- mpt += sizeof(struct mpc_config_bus);
- count += sizeof(struct mpc_config_bus);
- break;
- case MP_INTSRC:
- ++num_irq;
- mpt += sizeof(struct mpc_config_intsrc);
- count += sizeof(struct mpc_config_intsrc);
- break;
- case MP_IOAPIC:
- mpt += sizeof(struct mpc_config_ioapic);
- count += sizeof(struct mpc_config_ioapic);
- break;
- case MP_LINTSRC:
- mpt += sizeof(struct mpc_config_lintsrc);
- count += sizeof(struct mpc_config_lintsrc);
- break;
- default:
- count = mpc->mpc_length;
- break;
- }
- }
- /*
- * Paranoia: Allocate one extra of both the number of busses and number
- * of irqs, and make sure that we have at least 4 interrupts per PCI
- * slot. But some machines do not report very many busses, so we need
- * to fall back on the older defaults.
- */
- ++num_bus;
- max_mp_busses = max(num_bus, MAX_MP_BUSSES);
- if (num_irq < (4 * max_mp_busses))
- num_irq = 4 * num_bus; /* 4 intr/PCI slot */
- ++num_irq;
- max_irq_sources = max(num_irq, MAX_IRQ_SOURCES);
-
- count = (max_mp_busses * sizeof(int)) * 4;
- count += (max_irq_sources * sizeof(struct mpc_config_intsrc));
- bus_data = (void *)alloc_xenheap_pages(get_order(count));
- if (!bus_data) {
- printk(KERN_ERR "SMP mptable: out of memory!\n");
- return 0;
- }
- mp_bus_id_to_type = (int *)&bus_data[0];
- mp_bus_id_to_node = (int *)&bus_data[(max_mp_busses * sizeof(int))];
- mp_bus_id_to_local = (int *)&bus_data[(max_mp_busses * sizeof(int)) * 2];
- mp_bus_id_to_pci_bus = (int *)&bus_data[(max_mp_busses * sizeof(int)) * 3];
- mp_irqs = (struct mpc_config_intsrc *)&bus_data[(max_mp_busses * sizeof(int)) * 4];
- memset(mp_bus_id_to_pci_bus, -1, max_mp_busses * sizeof(int));
-
/*
* Now process the configuration blocks.
*/
- count = sizeof(*mpc);
- mpt = ((unsigned char *)mpc)+count;
+ mpc_record = 0;
while (count < mpc->mpc_length) {
switch(*mpt) {
case MP_PROCESSOR:
}
++mpc_record;
}
-
- if (clustered_apic_mode){
- phys_cpu_present_map = logical_cpu_present_map;
- }
-
-
- printk("Enabling APIC mode: ");
- if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ)
- printk("Clustered Logical. ");
- else if(clustered_apic_mode == CLUSTERED_APIC_XAPIC)
- printk("Physical. ");
- else
- printk("Flat. ");
- printk("Using %d I/O APICs\n",nr_ioapics);
-
+ clustered_apic_check();
if (!num_processors)
printk(KERN_ERR "SMP mptable: no processors registered!\n");
return num_processors;
* If it does, we assume it's valid.
*/
if (mpc_default_type == 5) {
- printk("ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
+ printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
- printk("ELCR contains invalid data... not using ELCR\n");
+ printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n");
else {
- printk("Using ELCR to identify PCI interrupts\n");
+ printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
ELCR_fallback = 1;
}
}
struct mpc_config_lintsrc lintsrc;
int linttypes[2] = { mp_ExtINT, mp_NMI };
int i;
- struct {
- int mp_bus_id_to_type[MAX_MP_BUSSES];
- int mp_bus_id_to_node[MAX_MP_BUSSES];
- int mp_bus_id_to_local[MAX_MP_BUSSES];
- int mp_bus_id_to_pci_bus[MAX_MP_BUSSES];
- struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
- } *bus_data;
-
- bus_data = (void *)alloc_xenheap_pages(get_order(sizeof(*bus_data)));
- if (!bus_data)
- panic("SMP mptable: out of memory!\n");
- mp_bus_id_to_type = bus_data->mp_bus_id_to_type;
- mp_bus_id_to_node = bus_data->mp_bus_id_to_node;
- mp_bus_id_to_local = bus_data->mp_bus_id_to_local;
- mp_bus_id_to_pci_bus = bus_data->mp_bus_id_to_pci_bus;
- mp_irqs = bus_data->mp_irqs;
- for (i = 0; i < MAX_MP_BUSSES; ++i)
- mp_bus_id_to_pci_bus[i] = -1;
/*
* local APIC has default address
bus.mpc_busid = 0;
switch (mpc_default_type) {
default:
- printk("???\nUnknown standard configuration %d\n",
+ printk("???\n");
+ printk(KERN_ERR "Unknown standard configuration %d\n",
mpc_default_type);
/* fall through */
case 1:
/*
* ACPI may be used to obtain the entire SMP configuration or just to
- * enumerate/configure processors (CONFIG_ACPI_HT_ONLY). Note that
+ * enumerate/configure processors (CONFIG_ACPI_BOOT). Note that
* ACPI supports both logical (e.g. Hyper-Threading) and physical
* processors, where MPS only supports physical.
*/
else if (acpi_lapic)
printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
- printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
+ printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
if (mpf->mpf_feature2 & (1<<7)) {
- printk(" IMCR and PIC compatibility mode.\n");
+ printk(KERN_INFO " IMCR and PIC compatibility mode.\n");
pic_mode = 1;
} else {
- printk(" Virtual Wire compatibility mode.\n");
+ printk(KERN_INFO " Virtual Wire compatibility mode.\n");
pic_mode = 0;
}
*/
if (mpf->mpf_feature1 != 0) {
- printk("Default MP configuration #%d\n", mpf->mpf_feature1);
+ printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
construct_default_ISA_mptable(mpf->mpf_feature1);
} else if (mpf->mpf_physptr) {
* Read the physical hardware table. Anything here will
* override the defaults.
*/
- if (!smp_read_mpc((void *)(unsigned long)mpf->mpf_physptr)) {
+ if (!smp_read_mpc((void *)mpf->mpf_physptr)) {
smp_found_config = 0;
printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
if (!mp_irq_entries) {
struct mpc_config_bus bus;
- printk("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
+ printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
bus.mpc_type = MP_BUS;
bus.mpc_busid = 0;
} else
BUG();
- printk("Processors: %d\n", num_processors);
+ printk(KERN_INFO "Processors: %d\n", num_processors);
/*
* Only use the first configuration found.
*/
static int __init smp_scan_config (unsigned long base, unsigned long length)
{
- unsigned int *bp = phys_to_virt(base);
+ unsigned long *bp = phys_to_virt(base);
struct intel_mp_floating *mpf;
Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
|| (mpf->mpf_specification == 4)) ) {
smp_found_config = 1;
- printk("found SMP MP-table at %08lx\n",
+ printk(KERN_INFO "found SMP MP-table at %08lx\n",
virt_to_phys(mpf));
+#if 0
reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
- if (mpf->mpf_physptr)
- reserve_bootmem((unsigned long)mpf->mpf_physptr, PAGE_SIZE);
+ if (mpf->mpf_physptr) {
+ /*
+ * We cannot access to MPC table to compute
+ * table size yet, as only few megabytes from
+ * the bottom is mapped now.
+ * PC-9800's MPC table places on the very last
+ * of physical memory; so that simply reserving
+ * PAGE_SIZE from mpg->mpf_physptr yields BUG()
+ * in reserve_bootmem.
+ */
+ unsigned long size = PAGE_SIZE;
+ unsigned long end = max_low_pfn * PAGE_SIZE;
+ if (mpf->mpf_physptr + size > end)
+ size = end - mpf->mpf_physptr;
+ reserve_bootmem(mpf->mpf_physptr, size);
+ }
+#endif
mpf_found = mpf;
return 1;
}
return 0;
}
-void __init find_intel_smp (void)
+void __init find_smp_config (void)
{
unsigned int address;
* there is a real-mode segmented pointer pointing to the
* 4K EBDA area at 0x40E, calculate and scan it here.
*
- * NOTE! There were Linux loaders that will corrupt the EBDA
+ * NOTE! There are Linux loaders that will corrupt the EBDA
* area, and as such this kind of SMP config may be less
* trustworthy, simply because the SMP table may have been
- * stomped on during early boot. Thankfully the bootloaders
- * now honour the EBDA.
+ * stomped on during early boot. These loaders are buggy and
+ * should be fixed.
+ *
+ * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
*/
- address = *(unsigned short *)phys_to_virt(0x40E);
- address <<= 4;
- smp_scan_config(address, 0x1000);
+ address = get_bios_ebda();
+ if (address)
+ smp_scan_config(address, 0x400);
}
-#else
-
-/*
- * The Visual Workstation is Intel MP compliant in the hardware
- * sense, but it doesn't have a BIOS(-configuration table).
- * No problem for Linux.
- */
-void __init find_visws_smp(void)
-{
- smp_found_config = 1;
-
- phys_cpu_present_map |= 2; /* or in id 1 */
- apic_version[1] |= 0x10; /* integrated APIC */
- apic_version[0] |= 0x10;
-
- mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-}
-
-#endif
-
-/*
- * - Intel MP Configuration Table
- * - or SGI Visual Workstation configuration
- */
-void __init find_smp_config (void)
-{
-#ifdef CONFIG_X86_LOCAL_APIC
- find_intel_smp();
-#endif
-#ifdef CONFIG_VISWS
- find_visws_smp();
-#endif
-}
-
-
/* --------------------------------------------------------------------------
ACPI-based MP Configuration
-------------------------------------------------------------------------- */
struct mpc_config_processor processor;
int boot_cpu = 0;
- if (id >= MAX_APICS) {
+ if (MAX_APICS - id <= 0) {
printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
id, MAX_APICS);
return;
processor.mpc_type = MP_PROCESSOR;
processor.mpc_apicid = id;
-
- /*
- * mp_register_lapic_address() which is called before the
- * current function does the fixmap of FIX_APIC_BASE.
- * Read in the correct APIC version from there
- */
- processor.mpc_apicver = apic_read(APIC_LVR);
-
+ processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
MP_processor_info(&processor);
}
-#if defined(CONFIG_X86_IO_APIC) /*&& defined(CONFIG_ACPI_INTERPRETER)*/
+#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
#define MP_ISA_BUS 0
#define MP_MAX_IOAPIC_PIN 127
struct mp_ioapic_routing {
int apic_id;
- int irq_start;
- int irq_end;
+ int gsi_base;
+ int gsi_end;
u32 pin_programmed[4];
} mp_ioapic_routing[MAX_IO_APICS];
-static int __init mp_find_ioapic (
- int irq)
+static int mp_find_ioapic (
+ int gsi)
{
int i = 0;
- /* Find the IOAPIC that manages this IRQ. */
+ /* Find the IOAPIC that manages this GSI. */
for (i = 0; i < nr_ioapics; i++) {
- if ((irq >= mp_ioapic_routing[i].irq_start)
- && (irq <= mp_ioapic_routing[i].irq_end))
+ if ((gsi >= mp_ioapic_routing[i].gsi_base)
+ && (gsi <= mp_ioapic_routing[i].gsi_end))
return i;
}
- printk(KERN_ERR "ERROR: Unable to locate IOAPIC for IRQ %d\n", irq);
+ printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
return -1;
}
void __init mp_register_ioapic (
u8 id,
u32 address,
- u32 irq_base)
+ u32 gsi_base)
{
int idx = 0;
mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
/*
- * Build basic IRQ lookup table to facilitate irq->io_apic lookups
- * and to prevent reprogramming of IOAPIC pins (PCI IRQs).
+ * Build basic GSI lookup table to facilitate gsi->io_apic lookups
+ * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
*/
mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
- mp_ioapic_routing[idx].irq_start = irq_base;
- mp_ioapic_routing[idx].irq_end = irq_base +
+ mp_ioapic_routing[idx].gsi_base = gsi_base;
+ mp_ioapic_routing[idx].gsi_end = gsi_base +
io_apic_get_redir_entries(idx);
printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
- "IRQ %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
+ "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
- mp_ioapic_routing[idx].irq_start,
- mp_ioapic_routing[idx].irq_end);
+ mp_ioapic_routing[idx].gsi_base,
+ mp_ioapic_routing[idx].gsi_end);
return;
}
u8 bus_irq,
u8 polarity,
u8 trigger,
- u32 global_irq)
+ u32 gsi)
{
struct mpc_config_intsrc intsrc;
- int i = 0;
- int found = 0;
int ioapic = -1;
int pin = -1;
/*
- * Convert 'global_irq' to 'ioapic.pin'.
+ * Convert 'gsi' to 'ioapic.pin'.
*/
- ioapic = mp_find_ioapic(global_irq);
+ ioapic = mp_find_ioapic(gsi);
if (ioapic < 0)
return;
- pin = global_irq - mp_ioapic_routing[ioapic].irq_start;
+ pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
/*
* TBD: This check is for faulty timer entries, where the override
(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
- /*
- * If an existing [IOAPIC.PIN -> IRQ] routing entry exists we override it.
- * Otherwise create a new entry (e.g. global_irq == 2).
- */
- for (i = 0; i < mp_irq_entries; i++) {
- if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus)
- && (mp_irqs[i].mpc_srcbusirq == intsrc.mpc_srcbusirq)) {
- mp_irqs[i] = intsrc;
- found = 1;
- break;
- }
- }
- if (!found) {
- mp_irqs[mp_irq_entries] = intsrc;
- if (++mp_irq_entries == MAX_IRQ_SOURCES)
- panic("Max # of irq sources exceeded!\n");
- }
+ mp_irqs[mp_irq_entries] = intsrc;
+ if (++mp_irq_entries == MAX_IRQ_SOURCES)
+ panic("Max # of irq sources exceeded!\n");
return;
}
void __init mp_config_acpi_legacy_irqs (void)
{
+ struct mpc_config_intsrc intsrc;
int i = 0;
int ioapic = -1;
- /*
- * Initialize mp_irqs for IRQ configuration.
- */
- unsigned char *bus_data;
- int count;
-
- count = (MAX_MP_BUSSES * sizeof(int)) * 4;
- count += (MAX_IRQ_SOURCES * sizeof(int)) * 4;
- bus_data = (void *)alloc_xenheap_pages(get_order(count));
- if (!bus_data) {
- panic("Fatal: can't allocate bus memory for ACPI legacy IRQ!");
- }
- mp_bus_id_to_type = (int *)&bus_data[0];
- mp_bus_id_to_node = (int *)&bus_data[(MAX_MP_BUSSES * sizeof(int))];
- mp_bus_id_to_local = (int *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 2];
- mp_bus_id_to_pci_bus = (int *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 3];
- mp_irqs = (struct mpc_config_intsrc *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 4];
- for (i = 0; i < MAX_MP_BUSSES; ++i)
- mp_bus_id_to_pci_bus[i] = -1;
-
/*
* Fabricate the legacy ISA bus (bus #31).
*/
mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
+ /*
+ * ES7000 has no legacy identity mappings
+ */
+ if (es7000_plat)
+ return;
+
/*
* Locate the IOAPIC that manages the ISA IRQs (0-15).
*/
if (ioapic < 0)
return;
+ intsrc.mpc_type = MP_INTSRC;
+ intsrc.mpc_irqflag = 0; /* Conforming */
+ intsrc.mpc_srcbus = MP_ISA_BUS;
+ intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
+
/*
- * Use the default configuration for the IRQs 0-15. These may be
+ * Use the default configuration for the IRQs 0-15. Unless
* overriden by (MADT) interrupt source override entries.
*/
for (i = 0; i < 16; i++) {
+ int idx;
- if (i == 2)
- continue; /* Don't connect IRQ2 */
+ for (idx = 0; idx < mp_irq_entries; idx++) {
+ struct mpc_config_intsrc *irq = mp_irqs + idx;
- mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC;
- mp_irqs[mp_irq_entries].mpc_irqflag = 0; /* Conforming */
- mp_irqs[mp_irq_entries].mpc_srcbus = MP_ISA_BUS;
- mp_irqs[mp_irq_entries].mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
- mp_irqs[mp_irq_entries].mpc_irqtype = mp_INT;
- mp_irqs[mp_irq_entries].mpc_srcbusirq = i; /* Identity mapped */
- mp_irqs[mp_irq_entries].mpc_dstirq = i;
+ /* Do we already have a mapping for this ISA IRQ? */
+ if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
+ break;
+
+ /* Do we already have a mapping for this IOAPIC pin */
+ if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
+ (irq->mpc_dstirq == i))
+ break;
+ }
+
+ if (idx != mp_irq_entries) {
+ printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
+ continue; /* IRQ already used */
+ }
+
+ intsrc.mpc_irqtype = mp_INT;
+ intsrc.mpc_srcbusirq = i; /* Identity mapped */
+ intsrc.mpc_dstirq = i;
Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
- "%d-%d\n",
- mp_irqs[mp_irq_entries].mpc_irqtype,
- mp_irqs[mp_irq_entries].mpc_irqflag & 3,
- (mp_irqs[mp_irq_entries].mpc_irqflag >> 2) & 3,
- mp_irqs[mp_irq_entries].mpc_srcbus,
- mp_irqs[mp_irq_entries].mpc_srcbusirq,
- mp_irqs[mp_irq_entries].mpc_dstapic,
- mp_irqs[mp_irq_entries].mpc_dstirq);
+ "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3,
+ (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
+ intsrc.mpc_srcbusirq, intsrc.mpc_dstapic,
+ intsrc.mpc_dstirq);
+ mp_irqs[mp_irq_entries] = intsrc;
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!\n");
}
}
-#ifdef CONFIG_ACPI_PCI
-
-void __init mp_parse_prt (void)
+int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
{
- struct acpi_prt_entry *entry = NULL;
int ioapic = -1;
int ioapic_pin = 0;
- int irq = 0;
int idx, bit = 0;
- int edge_level = 0;
- int active_high_low = 0;
- /*
- * Parsing through the PCI Interrupt Routing Table (PRT) and program
- * routing for all entries.
- */
- list_for_each_entry(entry, &acpi_prt.entries, node) {
- /* Need to get irq for dynamic entry */
- if (entry->link.handle) {
- irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
- if (!irq)
- continue;
- }
- else {
- /* Hardwired IRQ. Assume PCI standard settings */
- irq = entry->link.index;
- edge_level = 1;
- active_high_low = 1;
- }
+#ifdef CONFIG_ACPI_BUS
+ /* Don't set up the ACPI SCI because it's already set up */
+ if (acpi_fadt.sci_int == gsi)
+ return gsi;
+#endif
- /* Don't set up the ACPI SCI because it's already set up */
- if (acpi_fadt.sci_int == irq) {
- entry->irq = irq; /*we still need to set entry's irq*/
- continue;
- }
-
- ioapic = mp_find_ioapic(irq);
- if (ioapic < 0)
- continue;
- ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start;
-
- /*
- * Avoid pin reprogramming. PRTs typically include entries
- * with redundant pin->irq mappings (but unique PCI devices);
- * we only only program the IOAPIC on the first.
- */
- bit = ioapic_pin % 32;
- idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
- if (idx > 3) {
- printk(KERN_ERR "Invalid reference to IOAPIC pin "
- "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
- ioapic_pin);
- continue;
- }
- if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
- Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
- mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
- entry->irq = irq;
- continue;
- }
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0) {
+ printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+ return gsi;
+ }
- mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+ ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
- if (!io_apic_set_pci_routing(ioapic, ioapic_pin, irq, edge_level, active_high_low))
- entry->irq = irq;
+ if (ioapic_renumber_irq)
+ gsi = ioapic_renumber_irq(ioapic, gsi);
- printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n",
- entry->id.segment, entry->id.bus,
- entry->id.device, ('A' + entry->pin),
- mp_ioapic_routing[ioapic].apic_id, ioapic_pin,
- entry->irq);
+ /*
+ * Avoid pin reprogramming. PRTs typically include entries
+ * with redundant pin->gsi mappings (but unique PCI devices);
+ * we only program the IOAPIC on the first.
+ */
+ bit = ioapic_pin % 32;
+ idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+ if (idx > 3) {
+ printk(KERN_ERR "Invalid reference to IOAPIC pin "
+ "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
+ ioapic_pin);
+ return gsi;
+ }
+ if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+ Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+ mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+ return gsi;
}
-
- print_IO_APIC();
-
- return;
-}
-#endif /*CONFIG_ACPI_PCI*/
+ mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
-#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
+ io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+ edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
+ active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
+ return gsi;
+}
-#endif /*CONFIG_ACPI*/
+#endif /*CONFIG_X86_IO_APIC && (CONFIG_ACPI_INTERPRETER || CONFIG_ACPI_BOOT)*/
+#endif /*CONFIG_ACPI_BOOT*/
#include <xen/init.h>
#include <xen/pci.h>
#include <xen/smp.h>
+#include <xen/spinlock.h>
#include <asm/mtrr.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
int __init check_nmi_watchdog (void)
{
unsigned int prev_nmi_count[NR_CPUS];
- int j, cpu;
+ int cpu;
if ( !nmi_watchdog )
return 0;
printk("Testing NMI watchdog --- ");
- for ( j = 0; j < smp_num_cpus; j++ )
- {
- cpu = cpu_logical_map(j);
+ for ( cpu = 0; cpu < smp_num_cpus; cpu++ )
prev_nmi_count[cpu] = nmi_count(cpu);
- }
__sti();
mdelay((10*1000)/nmi_hz); /* wait 10 ticks */
- for ( j = 0; j < smp_num_cpus; j++ )
+ for ( cpu = 0; cpu < smp_num_cpus; cpu++ )
{
- cpu = cpu_logical_map(j);
if ( nmi_count(cpu) - prev_nmi_count[cpu] <= 5 )
printk("CPU#%d stuck. ", cpu);
else
#include <public/xen.h>
#include <public/physdev.h>
-extern void (*interrupt[])(void);
-
extern int ioapic_guest_read(int apicid, int address, u32 *pval);
extern int ioapic_guest_write(int apicid, int address, u32 pval);
#include <xen/sched.h>
#include <xen/delay.h>
#include <xen/lib.h>
-
-#ifdef CONFIG_SMP
+#include <mach_apic.h>
+#include <mach_wakecpu.h>
/* Cconfigured maximum number of CPUs to activate. We name the parameter
"maxcpus" rather than max_cpus to be compatible with Linux */
int ht_per_core = 1;
/* Bitmask of currently online CPUs */
-unsigned long cpu_online_map;
+cpumask_t cpu_online_map;
-static volatile unsigned long cpu_callin_map;
-static volatile unsigned long cpu_callout_map;
+cpumask_t cpu_callin_map;
+cpumask_t cpu_callout_map;
/* Per CPU bogomips and other parameters */
struct cpuinfo_x86 cpu_data[NR_CPUS];
if (!smp_found_config) {
printk("SMP motherboard not detected.\n");
io_apic_irqs = 0;
- cpu_online_map = phys_cpu_present_map = 1;
+ phys_cpu_present_map = physid_mask_of_physid(0);
+ cpu_online_map = 1;
smp_num_cpus = 1;
if (APIC_init_uniprocessor())
printk("Local APIC not detected."
if (!test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map)) {
printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
boot_cpu_physical_apicid);
- phys_cpu_present_map |= (1 << hard_smp_processor_id());
+ physid_set(hard_smp_processor_id(), phys_cpu_present_map);
}
/*
boot_cpu_physical_apicid);
printk("... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
io_apic_irqs = 0;
- cpu_online_map = phys_cpu_present_map = 1;
+ phys_cpu_present_map = physid_mask_of_physid(0);
+ cpu_online_map = 1;
smp_num_cpus = 1;
goto smp_done;
}
smp_found_config = 0;
printk("SMP mode deactivated, forcing use of dummy APIC emulation.\n");
io_apic_irqs = 0;
- cpu_online_map = phys_cpu_present_map = 1;
+ phys_cpu_present_map = physid_mask_of_physid(0);
+ cpu_online_map = 1;
smp_num_cpus = 1;
goto smp_done;
}
if (opt_noht && (apicid & (ht_per_core - 1)))
continue;
- if (!(phys_cpu_present_map & (1 << bit)))
+ if (!check_apicid_present(bit))
continue;
if ((max_cpus >= 0) && (max_cpus <= cpucount+1))
continue;
* Make sure we unmap all failed CPUs
*/
if ((boot_apicid_to_cpu(apicid) == -1) &&
- (phys_cpu_present_map & (1 << bit)))
+ (!check_apicid_present(bit)))
printk("CPU #%d not responding - cannot use it.\n",
apicid);
}
if ( nr_ioapics ) setup_IO_APIC();
/* Set up all local APIC timers in the system. */
- setup_APIC_clocks();
+ {
+ extern void setup_APIC_clocks(void);
+ setup_APIC_clocks();
+ }
/* Synchronize the TSC with the AP(s). */
if ( cpucount ) synchronize_tsc_bp();
;
}
-#endif /* CONFIG_SMP */
-
/*
* Local variables:
* mode: C
OFFSET(MULTICALL_result, multicall_entry_t, args[5]);
BLANK();
- DEFINE(FIXMAP_apic_base, fix_to_virt(FIX_APIC_BASE));
+ DEFINE(FIXMAP_apic_base, __fix_to_virt(FIX_APIC_BASE));
BLANK();
DEFINE(IRQSTAT_shift, LOG_2(sizeof(irq_cpustat_t)));
{
if ( unlikely(idx >= __end_of_fixed_addresses) )
BUG();
- map_pages(idle_pg_table, fix_to_virt(idx), p, PAGE_SIZE, flags);
+ map_pages(idle_pg_table, __fix_to_virt(idx), p, PAGE_SIZE, flags);
}
return 0;
}
- /*
- * We only fast-trap vectors 0x20-0x2f, and vector 0x80.
- * The former range is used by Windows and MS-DOS.
- * Vector 0x80 is used by Linux and the BSD variants.
- */
- if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) )
+ /* We only fast-trap vector 0x80 (used by Linux and the BSD variants). */
+ if ( idx != 0x80 )
return -1;
ti = &p->arch.guest_context.trap_ctxt[idx];
{
if ( unlikely(idx >= __end_of_fixed_addresses) )
BUG();
- map_pages(idle_pg_table, fix_to_virt(idx), p, PAGE_SIZE, flags);
+ map_pages(idle_pg_table, __fix_to_virt(idx), p, PAGE_SIZE, flags);
}
--- /dev/null
+/*
+ * lib/bitmap.c
+ * Helper functions for bitmap.h.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/errno.h>
+#include <xen/bitmap.h>
+#include <xen/bitops.h>
+#include <asm/uaccess.h>
+
+/*
+ * bitmaps provide an array of bits, implemented using an an
+ * array of unsigned longs. The number of valid bits in a
+ * given bitmap does _not_ need to be an exact multiple of
+ * BITS_PER_LONG.
+ *
+ * The possible unused bits in the last, partially used word
+ * of a bitmap are 'don't care'. The implementation makes
+ * no particular effort to keep them zero. It ensures that
+ * their value will not affect the results of any operation.
+ * The bitmap operations that return Boolean (bitmap_empty,
+ * for example) or scalar (bitmap_weight, for example) results
+ * carefully filter out these unused bits from impacting their
+ * results.
+ *
+ * These operations actually hold to a slightly stronger rule:
+ * if you don't input any bitmaps to these ops that have some
+ * unused bits set, then they won't output any set unused bits
+ * in output bitmaps.
+ *
+ * The byte ordering of bitmaps is more natural on little
+ * endian architectures. See the big-endian headers
+ * include/asm-ppc64/bitops.h and include/asm-s390/bitops.h
+ * for the best explanations of this ordering.
+ */
+
+int __bitmap_empty(const unsigned long *bitmap, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ if (bitmap[k])
+ return 0;
+
+ if (bits % BITS_PER_LONG)
+ if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
+ return 0;
+
+ return 1;
+}
+EXPORT_SYMBOL(__bitmap_empty);
+
+int __bitmap_full(const unsigned long *bitmap, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ if (~bitmap[k])
+ return 0;
+
+ if (bits % BITS_PER_LONG)
+ if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
+ return 0;
+
+ return 1;
+}
+EXPORT_SYMBOL(__bitmap_full);
+
+int __bitmap_equal(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ if (bitmap1[k] != bitmap2[k])
+ return 0;
+
+ if (bits % BITS_PER_LONG)
+ if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
+ return 0;
+
+ return 1;
+}
+EXPORT_SYMBOL(__bitmap_equal);
+
+void __bitmap_complement(unsigned long *dst, const unsigned long *src, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ dst[k] = ~src[k];
+
+ if (bits % BITS_PER_LONG)
+ dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits);
+}
+EXPORT_SYMBOL(__bitmap_complement);
+
+/*
+ * __bitmap_shift_right - logical right shift of the bits in a bitmap
+ * @dst - destination bitmap
+ * @src - source bitmap
+ * @nbits - shift by this many bits
+ * @bits - bitmap size, in bits
+ *
+ * Shifting right (dividing) means moving bits in the MS -> LS bit
+ * direction. Zeros are fed into the vacated MS positions and the
+ * LS bits shifted off the bottom are lost.
+ */
+void __bitmap_shift_right(unsigned long *dst,
+ const unsigned long *src, int shift, int bits)
+{
+ int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
+ int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
+ unsigned long mask = (1UL << left) - 1;
+ for (k = 0; off + k < lim; ++k) {
+ unsigned long upper, lower;
+
+ /*
+ * If shift is not word aligned, take lower rem bits of
+ * word above and make them the top rem bits of result.
+ */
+ if (!rem || off + k + 1 >= lim)
+ upper = 0;
+ else {
+ upper = src[off + k + 1];
+ if (off + k + 1 == lim - 1 && left)
+ upper &= mask;
+ }
+ lower = src[off + k];
+ if (left && off + k == lim - 1)
+ lower &= mask;
+ dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem;
+ if (left && k == lim - 1)
+ dst[k] &= mask;
+ }
+ if (off)
+ memset(&dst[lim - off], 0, off*sizeof(unsigned long));
+}
+EXPORT_SYMBOL(__bitmap_shift_right);
+
+
+/*
+ * __bitmap_shift_left - logical left shift of the bits in a bitmap
+ * @dst - destination bitmap
+ * @src - source bitmap
+ * @nbits - shift by this many bits
+ * @bits - bitmap size, in bits
+ *
+ * Shifting left (multiplying) means moving bits in the LS -> MS
+ * direction. Zeros are fed into the vacated LS bit positions
+ * and those MS bits shifted off the top are lost.
+ */
+
+void __bitmap_shift_left(unsigned long *dst,
+ const unsigned long *src, int shift, int bits)
+{
+ int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
+ int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
+ for (k = lim - off - 1; k >= 0; --k) {
+ unsigned long upper, lower;
+
+ /*
+ * If shift is not word aligned, take upper rem bits of
+ * word below and make them the bottom rem bits of result.
+ */
+ if (rem && k > 0)
+ lower = src[k - 1];
+ else
+ lower = 0;
+ upper = src[k];
+ if (left && k == lim - 1)
+ upper &= (1UL << left) - 1;
+ dst[k + off] = lower >> (BITS_PER_LONG - rem) | upper << rem;
+ if (left && k + off == lim - 1)
+ dst[k + off] &= (1UL << left) - 1;
+ }
+ if (off)
+ memset(dst, 0, off*sizeof(unsigned long));
+}
+EXPORT_SYMBOL(__bitmap_shift_left);
+
+void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k;
+ int nr = BITS_TO_LONGS(bits);
+
+ for (k = 0; k < nr; k++)
+ dst[k] = bitmap1[k] & bitmap2[k];
+}
+EXPORT_SYMBOL(__bitmap_and);
+
+void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k;
+ int nr = BITS_TO_LONGS(bits);
+
+ for (k = 0; k < nr; k++)
+ dst[k] = bitmap1[k] | bitmap2[k];
+}
+EXPORT_SYMBOL(__bitmap_or);
+
+void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k;
+ int nr = BITS_TO_LONGS(bits);
+
+ for (k = 0; k < nr; k++)
+ dst[k] = bitmap1[k] ^ bitmap2[k];
+}
+EXPORT_SYMBOL(__bitmap_xor);
+
+void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k;
+ int nr = BITS_TO_LONGS(bits);
+
+ for (k = 0; k < nr; k++)
+ dst[k] = bitmap1[k] & ~bitmap2[k];
+}
+EXPORT_SYMBOL(__bitmap_andnot);
+
+int __bitmap_intersects(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ if (bitmap1[k] & bitmap2[k])
+ return 1;
+
+ if (bits % BITS_PER_LONG)
+ if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL(__bitmap_intersects);
+
+int __bitmap_subset(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits)
+{
+ int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ if (bitmap1[k] & ~bitmap2[k])
+ return 0;
+
+ if (bits % BITS_PER_LONG)
+ if ((bitmap1[k] & ~bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
+ return 0;
+ return 1;
+}
+EXPORT_SYMBOL(__bitmap_subset);
+
+#if BITS_PER_LONG == 32
+int __bitmap_weight(const unsigned long *bitmap, int bits)
+{
+ int k, w = 0, lim = bits/BITS_PER_LONG;
+
+ for (k = 0; k < lim; k++)
+ w += hweight32(bitmap[k]);
+
+ if (bits % BITS_PER_LONG)
+ w += hweight32(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
+
+ return w;
+}
+#else
+int __bitmap_weight(const unsigned long *bitmap, int bits)
+{
+ int k, w = 0, lim = bits/BITS_PER_LONG;
+
+ for (k = 0; k < lim; k++)
+ w += hweight64(bitmap[k]);
+
+ if (bits % BITS_PER_LONG)
+ w += hweight64(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
+
+ return w;
+}
+#endif
+EXPORT_SYMBOL(__bitmap_weight);
+
+/**
+ * bitmap_find_free_region - find a contiguous aligned mem region
+ * @bitmap: an array of unsigned longs corresponding to the bitmap
+ * @bits: number of bits in the bitmap
+ * @order: region size to find (size is actually 1<<order)
+ *
+ * This is used to allocate a memory region from a bitmap. The idea is
+ * that the region has to be 1<<order sized and 1<<order aligned (this
+ * makes the search algorithm much faster).
+ *
+ * The region is marked as set bits in the bitmap if a free one is
+ * found.
+ *
+ * Returns either beginning of region or negative error
+ */
+int bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
+{
+ unsigned long mask;
+ int pages = 1 << order;
+ int i;
+
+ if(pages > BITS_PER_LONG)
+ return -EINVAL;
+
+ /* make a mask of the order */
+ mask = (1ul << (pages - 1));
+ mask += mask - 1;
+
+ /* run up the bitmap pages bits at a time */
+ for (i = 0; i < bits; i += pages) {
+ int index = i/BITS_PER_LONG;
+ int offset = i - (index * BITS_PER_LONG);
+ if((bitmap[index] & (mask << offset)) == 0) {
+ /* set region in bimap */
+ bitmap[index] |= (mask << offset);
+ return i;
+ }
+ }
+ return -ENOMEM;
+}
+EXPORT_SYMBOL(bitmap_find_free_region);
+
+/**
+ * bitmap_release_region - release allocated bitmap region
+ * @bitmap: a pointer to the bitmap
+ * @pos: the beginning of the region
+ * @order: the order of the bits to release (number is 1<<order)
+ *
+ * This is the complement to __bitmap_find_free_region and releases
+ * the found region (by clearing it in the bitmap).
+ */
+void bitmap_release_region(unsigned long *bitmap, int pos, int order)
+{
+ int pages = 1 << order;
+ unsigned long mask = (1ul << (pages - 1));
+ int index = pos/BITS_PER_LONG;
+ int offset = pos - (index * BITS_PER_LONG);
+ mask += mask - 1;
+ bitmap[index] &= ~(mask << offset);
+}
+EXPORT_SYMBOL(bitmap_release_region);
+
+int bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
+{
+ int pages = 1 << order;
+ unsigned long mask = (1ul << (pages - 1));
+ int index = pos/BITS_PER_LONG;
+ int offset = pos - (index * BITS_PER_LONG);
+
+ /* We don't do regions of pages > BITS_PER_LONG. The
+ * algorithm would be a simple look for multiple zeros in the
+ * array, but there's no driver today that needs this. If you
+ * trip this BUG(), you get to code it... */
+ BUG_ON(pages > BITS_PER_LONG);
+ mask += mask - 1;
+ if (bitmap[index] & (mask << offset))
+ return -EBUSY;
+ bitmap[index] |= (mask << offset);
+ return 0;
+}
+EXPORT_SYMBOL(bitmap_allocate_region);
/* Total including this hdr. */
size_t size;
struct list_head freelist;
-} __attribute__((__aligned__(SMP_CACHE_BYTES)));
+} __cacheline_aligned;
static void maybe_split(struct xmalloc_hdr *hdr, size_t size, size_t block)
{
[ACPI_SSDT] = "SSDT",
[ACPI_SPMI] = "SPMI",
[ACPI_HPET] = "HPET",
+ [ACPI_MCFG] = "MCFG",
};
static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
else
name = header->signature;
- printk(KERN_INFO PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n",
+ printk(KERN_DEBUG PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n",
name, header->revision, header->oem_id,
header->oem_table_id, header->oem_revision,
header->asl_compiler_id, header->asl_compiler_revision,
{
struct acpi_table_ioapic *p =
(struct acpi_table_ioapic*) header;
- printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] global_irq_base[0x%x])\n",
+ printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
p->id, p->address, p->global_irq_base);
}
break;
{
struct acpi_table_iosapic *p =
(struct acpi_table_iosapic*) header;
- printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] global_irq_base[0x%x] address[%p])\n",
- p->id, p->global_irq_base, (void *) (unsigned long) p->address);
+ printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
+ p->id, (void *) (unsigned long) p->address, p->global_irq_base);
}
break;
*header = (void *) __acpi_map_table(fadt->V1_dsdt,
sizeof(struct acpi_table_header));
} else
- *header = 0;
+ *header = NULL;
if (!*header) {
printk(KERN_WARNING PREFIX "Unable to map DSDT\n");
enum acpi_table_id id,
unsigned long madt_size,
int entry_id,
- acpi_madt_entry_handler handler)
+ acpi_madt_entry_handler handler,
+ unsigned int max_entries)
{
void *madt = NULL;
- acpi_table_entry_header *entry = NULL;
- unsigned long count = 0;
- unsigned long madt_end = 0;
- unsigned int i = 0;
+ acpi_table_entry_header *entry;
+ unsigned int count = 0;
+ unsigned long madt_end;
+ unsigned int i;
if (!handler)
return -EINVAL;
entry = (acpi_table_entry_header *)
((unsigned long) madt + madt_size);
- while (((unsigned long) entry) < madt_end) {
- if (entry->type == entry_id) {
- count++;
- handler(entry);
- }
+ while (((unsigned long) entry) + sizeof(acpi_table_entry_header) < madt_end) {
+ if (entry->type == entry_id &&
+ (!max_entries || count++ < max_entries))
+ if (handler(entry, madt_end))
+ return -EINVAL;
+
entry = (acpi_table_entry_header *)
((unsigned long) entry + entry->length);
}
+ if (max_entries && count > max_entries) {
+ printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of "
+ "%i found\n", acpi_table_signatures[id], entry_id,
+ count - max_entries, count);
+ }
return count;
}
int __init
acpi_table_parse_madt (
enum acpi_madt_entry_id id,
- acpi_madt_entry_handler handler)
+ acpi_madt_entry_handler handler,
+ unsigned int max_entries)
{
return acpi_table_parse_madt_family(ACPI_APIC, sizeof(struct acpi_table_madt),
- id, handler);
+ id, handler, max_entries);
}
for (i = 0; i < sdt_count; i++) {
if (sdt_entry[i].id != id)
continue;
- handler(sdt_entry[i].pa, sdt_entry[i].size);
count++;
+ if (count == 1)
+ handler(sdt_entry[i].pa, sdt_entry[i].size);
+
+ else
+ printk(KERN_WARNING PREFIX "%d duplicate %s table ignored.\n",
+ count, acpi_table_signatures[id]);
}
return count;
return 0;
}
+/*
+ * acpi_table_init()
+ *
+ * find RSDP, find and checksum SDT/XSDT.
+ * checksum all tables, print SDT/XSDT
+ *
+ * result: sdt_entry[] is initialized
+ */
int __init
acpi_table_init (void)
return -ENODEV;
}
- printk(KERN_INFO PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n",
+ printk(KERN_DEBUG PREFIX "RSDP (v%3.3d %6.6s ) @ 0x%p\n",
rsdp->revision, rsdp->oem_id, (void *) rsdp_phys);
if (rsdp->revision < 2)
return 0;
}
-
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/* Version string */
-#define ACPI_CA_VERSION 0x20040116
+#define ACPI_CA_VERSION 0x20050211
+
+/*
+ * OS name, used for the _OS object. The _OS object is essentially obsolete,
+ * but there is a large base of ASL/AML code in existing machines that check
+ * for the string below. The use of this string usually guarantees that
+ * the ASL will execute down the most tested code path. Also, there is some
+ * code that will not execute the _OSI method unless _OS matches the string
+ * below. Therefore, change this string at your own risk.
+ */
+#define ACPI_OS_NAME "Microsoft Windows NT"
/* Maximum objects in the various object caches */
-#define ACPI_MAX_STATE_CACHE_DEPTH 64 /* State objects for stacks */
+#define ACPI_MAX_STATE_CACHE_DEPTH 64 /* State objects */
#define ACPI_MAX_PARSE_CACHE_DEPTH 96 /* Parse tree objects */
#define ACPI_MAX_EXTPARSE_CACHE_DEPTH 64 /* Parse tree objects */
#define ACPI_MAX_OBJECT_CACHE_DEPTH 64 /* Interpreter operand objects */
/* Version of ACPI supported */
-#define ACPI_CA_SUPPORT_LEVEL 2
+#define ACPI_CA_SUPPORT_LEVEL 3
/* String size constants */
/* Constants used in searching for the RSDP in low memory */
-#define ACPI_LO_RSDP_WINDOW_BASE 0 /* Physical Address */
-#define ACPI_HI_RSDP_WINDOW_BASE 0xE0000 /* Physical Address */
-#define ACPI_LO_RSDP_WINDOW_SIZE 0x400
-#define ACPI_HI_RSDP_WINDOW_SIZE 0x20000
+#define ACPI_EBDA_PTR_LOCATION 0x0000040E /* Physical Address */
+#define ACPI_EBDA_PTR_LENGTH 2
+#define ACPI_EBDA_WINDOW_SIZE 1024
+#define ACPI_HI_RSDP_WINDOW_BASE 0x000E0000 /* Physical Address */
+#define ACPI_HI_RSDP_WINDOW_SIZE 0x00020000
#define ACPI_RSDP_SCAN_STEP 16
/* Operation regions */
#define ACPI_SMBUS_BUFFER_SIZE 34
+/* Number of strings associated with the _OSI reserved method */
+
+#define ACPI_NUM_OSI_STRINGS 9
+
/******************************************************************************
*
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#define AE_LOGICAL_ADDRESS (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL)
#define AE_ABORT_METHOD (acpi_status) (0x001C | AE_CODE_ENVIRONMENTAL)
#define AE_SAME_HANDLER (acpi_status) (0x001D | AE_CODE_ENVIRONMENTAL)
+#define AE_WAKE_ONLY_GPE (acpi_status) (0x001E | AE_CODE_ENVIRONMENTAL)
-#define AE_CODE_ENV_MAX 0x001D
+#define AE_CODE_ENV_MAX 0x001E
/*
* Programmer exceptions
#define AE_AML_CIRCULAR_REFERENCE (acpi_status) (0x0020 | AE_CODE_AML)
#define AE_AML_BAD_RESOURCE_LENGTH (acpi_status) (0x0021 | AE_CODE_AML)
-#define AE_CODE_AML_MAX 0x0020
+#define AE_CODE_AML_MAX 0x0021
/*
* Internal exceptions used for control
"AE_NO_GLOBAL_LOCK",
"AE_LOGICAL_ADDRESS",
"AE_ABORT_METHOD",
- "AE_SAME_HANDLER"
+ "AE_SAME_HANDLER",
+ "AE_WAKE_ONLY_GPE"
};
char const *acpi_gbl_exception_names_pgm[] =
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/*
- * Ensure that the globals are actually defined only once.
+ * Ensure that the globals are actually defined and initialized only once.
*
- * The use of these defines allows a single list of globals (here) in order
+ * The use of these macros allows a single list of globals (here) in order
* to simplify maintenance of the code.
*/
#ifdef DEFINE_ACPI_GLOBALS
#define ACPI_EXTERN
+#define ACPI_INIT_GLOBAL(a,b) a=b
#else
#define ACPI_EXTERN extern
+#define ACPI_INIT_GLOBAL(a,b) a
#endif
+/*
+ * Keep local copies of these FADT-based registers. NOTE: These globals
+ * are first in this file for alignment reasons on 64-bit systems.
+ */
+ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable;
+ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable;
+
/*****************************************************************************
*
extern u32 acpi_gbl_nesting_level;
+/*****************************************************************************
+ *
+ * Runtime configuration (static defaults that can be overriden at runtime)
+ *
+ ****************************************************************************/
+
+/*
+ * Enable "slack" in the AML interpreter? Default is FALSE, and the
+ * interpreter strictly follows the ACPI specification. Setting to TRUE
+ * allows the interpreter to forgive certain bad AML constructs. Currently:
+ * 1) Allow "implicit return" of last value in a control method
+ * 2) Allow access beyond end of operation region
+ * 3) Allow access to uninitialized locals/args (auto-init to integer 0)
+ * 4) Allow ANY object type to be a source operand for the Store() operator
+ */
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_enable_interpreter_slack, FALSE);
+
+/*
+ * Automatically serialize ALL control methods? Default is FALSE, meaning
+ * to use the Serialized/not_serialized method flags on a per method basis.
+ * Only change this if the ASL code is poorly written and cannot handle
+ * reentrancy even though methods are marked "not_serialized".
+ */
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_all_methods_serialized, FALSE);
+
+/*
+ * Create the predefined _OSI method in the namespace? Default is TRUE
+ * because ACPI CA is fully compatible with other ACPI implementations.
+ * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior.
+ */
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_create_osi_method, TRUE);
+
+/*
+ * Disable wakeup GPEs during runtime? Default is TRUE because WAKE and
+ * RUNTIME GPEs should never be shared, and WAKE GPEs should typically only
+ * be enabled just before going to sleep.
+ */
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL (acpi_gbl_leave_wake_gpes_disabled, TRUE);
+
+
/*****************************************************************************
*
* ACPI Table globals
*
* These tables are single-table only; meaning that there can be at most one
* of each in the system. Each global points to the actual table.
- *
*/
ACPI_EXTERN u32 acpi_gbl_table_flags;
ACPI_EXTERN u32 acpi_gbl_rsdt_table_count;
ACPI_EXTERN struct acpi_table_header *acpi_gbl_DSDT;
ACPI_EXTERN FACS_DESCRIPTOR *acpi_gbl_FACS;
ACPI_EXTERN struct acpi_common_facs acpi_gbl_common_fACS;
+/*
+ * Since there may be multiple SSDTs and PSDTS, a single pointer is not
+ * sufficient; Therefore, there isn't one!
+ */
+
/*
* Handle both ACPI 1.0 and ACPI 2.0 Integer widths
ACPI_EXTERN u8 acpi_gbl_integer_byte_width;
ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
-/* Keep local copies of these FADT-based registers */
-
-ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable;
-ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable;
-
-/*
- * Since there may be multiple SSDTs and PSDTS, a single pointer is not
- * sufficient; Therefore, there isn't one!
- */
-
-
/*
* ACPI Table info arrays
*/
ACPI_EXTERN struct acpi_memory_list acpi_gbl_memory_lists[ACPI_NUM_MEM_LISTS];
ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify;
ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify;
+ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler;
ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler;
ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
ACPI_EXTERN acpi_handle acpi_gbl_global_lock_semaphore;
ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
ACPI_EXTERN u8 acpi_gbl_global_lock_present;
ACPI_EXTERN u8 acpi_gbl_events_initialized;
+ACPI_EXTERN u8 acpi_gbl_system_awake_and_running;
extern u8 acpi_gbl_shutdown;
extern u32 acpi_gbl_startup_flags;
extern const u8 acpi_gbl_decode_to8bit[8];
-extern const char *acpi_gbl_db_sleep_states[ACPI_S_STATE_COUNT];
+extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT];
+extern const char *acpi_gbl_highest_dstate_names[4];
extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES];
extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
+extern const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS];
/*****************************************************************************
#define NUM_NS_TYPES ACPI_TYPE_INVALID+1
-#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
+#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
#define NUM_PREDEFINED_NAMES 10
#else
#define NUM_PREDEFINED_NAMES 9
ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct;
ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node;
+ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device;
extern const u8 acpi_gbl_ns_properties[NUM_NS_TYPES];
extern const struct acpi_predefined_names acpi_gbl_pre_defined_names [NUM_PREDEFINED_NAMES];
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/* GPE support */
acpi_status
-acpi_hw_enable_gpe (
- struct acpi_gpe_event_info *gpe_event_info);
-
-void
-acpi_hw_enable_gpe_for_wakeup (
- struct acpi_gpe_event_info *gpe_event_info);
-
-acpi_status
-acpi_hw_disable_gpe (
+acpi_hw_write_gpe_enable_reg (
struct acpi_gpe_event_info *gpe_event_info);
acpi_status
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block);
-void
-acpi_hw_disable_gpe_for_wakeup (
- struct acpi_gpe_event_info *gpe_event_info);
-
acpi_status
acpi_hw_clear_gpe (
struct acpi_gpe_event_info *gpe_event_info);
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_hw_get_gpe_status (
struct acpi_gpe_event_info *gpe_event_info,
acpi_event_status *event_status);
+#endif
acpi_status
-acpi_hw_disable_non_wakeup_gpes (
- void);
+acpi_hw_disable_all_gpes (
+ u32 flags);
acpi_status
-acpi_hw_enable_non_wakeup_gpes (
- void);
+acpi_hw_enable_all_runtime_gpes (
+ u32 flags);
+
+acpi_status
+acpi_hw_enable_all_wakeup_gpes (
+ u32 flags);
+
+acpi_status
+acpi_hw_enable_runtime_gpe_block (
+ struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block);
+
+acpi_status
+acpi_hw_enable_wakeup_gpe_block (
+ struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block);
/* ACPI Timer prototypes */
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_get_timer_resolution (
u32 *resolution);
u32 start_ticks,
u32 end_ticks,
u32 *time_elapsed);
-
+#endif /* ACPI_FUTURE_USAGE */
#endif /* __ACHWARE_H__ */
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/* Total number of aml opcodes defined */
-#define AML_NUM_OPCODES 0x7E
+#define AML_NUM_OPCODES 0x7F
/*****************************************************************************
u8 type; /* Type associated with this name */
u16 owner_id;
union acpi_name_union name; /* ACPI Name, always 4 chars per ACPI spec */
-
-
union acpi_operand_object *object; /* Pointer to attached ACPI object (optional) */
struct acpi_namespace_node *child; /* First child */
struct acpi_namespace_node *peer; /* Next peer*/
#define ANOBJ_METHOD_LOCAL 0x10
#define ANOBJ_METHOD_NO_RETVAL 0x20
#define ANOBJ_METHOD_SOME_NO_RETVAL 0x40
-
#define ANOBJ_IS_BIT_OFFSET 0x80
-
/*
* ACPI Table Descriptor. One per ACPI table
*/
*
****************************************************************************/
-/* Information about a GPE, one per each GPE in an array */
+/* Dispatch info for each GPE -- either a method or handler, cannot be both */
-struct acpi_gpe_event_info
+struct acpi_handler_info
{
- struct acpi_namespace_node *method_node; /* Method node for this GPE level */
- acpi_gpe_handler handler; /* Address of handler, if any */
+ acpi_event_handler address; /* Address of handler, if any */
void *context; /* Context to be passed to handler */
+ struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */
+};
+
+union acpi_gpe_dispatch_info
+{
+ struct acpi_namespace_node *method_node; /* Method node for this GPE level */
+ struct acpi_handler_info *handler;
+};
+
+/*
+ * Information about a GPE, one per each GPE in an array.
+ * NOTE: Important to keep this struct as small as possible.
+ */
+struct acpi_gpe_event_info
+{
+ union acpi_gpe_dispatch_info dispatch; /* Either Method or Handler */
struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
- u8 flags; /* Level or Edge */
- u8 bit_mask; /* This GPE within the register */
+ u8 flags; /* Misc info about this GPE */
+ u8 register_bit; /* This GPE bit within the register */
};
/* Information about a GPE register pair, one per each status/enable pair in an array */
{
struct acpi_generic_address status_address; /* Address of status reg */
struct acpi_generic_address enable_address; /* Address of enable reg */
- u8 status; /* Current value of status reg */
- u8 enable; /* Current value of enable reg */
- u8 wake_enable; /* Mask of bits to keep enabled when sleeping */
+ u8 enable_for_wake; /* GPEs to keep enabled when sleeping */
+ u8 enable_for_run; /* GPEs to keep enabled when running */
u8 base_gpe_number; /* Base GPE number for this register */
};
*/
struct acpi_gpe_block_info
{
+ struct acpi_namespace_node *node;
struct acpi_gpe_block_info *previous;
struct acpi_gpe_block_info *next;
struct acpi_gpe_xrupt_info *xrupt_block; /* Backpointer to interrupt block */
};
+struct acpi_gpe_walk_info
+{
+ struct acpi_namespace_node *gpe_device;
+ struct acpi_gpe_block_info *gpe_block;
+};
+
+
typedef acpi_status (*ACPI_GPE_CALLBACK) (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block);
struct acpi_walk_state *walk_state_list; /* Head of list of walk_states for this thread */
union acpi_operand_object *acquired_mutex_list; /* List of all currently acquired mutexes */
u32 thread_id; /* Running thread ID */
- u16 current_sync_level; /* Mutex Sync (nested acquire) level */
+ u8 current_sync_level; /* Mutex Sync (nested acquire) level */
};
struct acpi_scope_state scope;
struct acpi_pscope_state parse_scope;
struct acpi_pkg_state pkg;
- struct acpi_thread_state acpi_thread;
+ struct acpi_thread_state thread;
struct acpi_result_values results;
struct acpi_notify_info notify;
};
/*
* Large resource descriptor types
*/
-
#define ACPI_RDESC_TYPE_MEMORY_24 0x81
#define ACPI_RDESC_TYPE_GENERAL_REGISTER 0x82
#define ACPI_RDESC_TYPE_LARGE_VENDOR 0x84
#define ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE 0x88
#define ACPI_RDESC_TYPE_EXTENDED_XRUPT 0x89
#define ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE 0x8A
+#define ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE 0x8B
/*****************************************************************************
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#define ACPI_LOBYTE(l) ((u8)(u16)(l))
#define ACPI_HIBYTE(l) ((u8)((((u16)(l)) >> 8) & 0xFF))
+#define ACPI_SET_BIT(target,bit) ((target) |= (bit))
+#define ACPI_CLEAR_BIT(target,bit) ((target) &= ~(bit))
+#define ACPI_MIN(a,b) (((a)<(b))?(a):(b))
+
#if ACPI_MACHINE_WIDTH == 16
* printf() format helpers
*/
-/* Split 64-bit integer into two 32-bit values. use with %8,8_x%8.8X */
+/* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */
#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i),ACPI_LODWORD(i)
#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7'))
-/* Macros for GAS addressing */
-
-#if ACPI_MACHINE_WIDTH != 16
-
-#define ACPI_PCI_DEVICE(a) (u16) ((ACPI_HIDWORD ((a))) & 0x0000FFFF)
-#define ACPI_PCI_FUNCTION(a) (u16) ((ACPI_LODWORD ((a))) >> 16)
-#define ACPI_PCI_REGISTER(a) (u16) ((ACPI_LODWORD ((a))) & 0x0000FFFF)
-
-#else
-
-/* No support for GAS and PCI IDs in 16-bit mode */
-
-#define ACPI_PCI_FUNCTION(a) (u16) ((a) & 0xFFFF0000)
-#define ACPI_PCI_DEVICE(a) (u16) ((a) & 0x0000FFFF)
-#define ACPI_PCI_REGISTER(a) (u16) ((a) & 0x0000FFFF)
-
-#endif
-
/* Bitfields within ACPI registers */
* The first parameter should be the procedure name as a quoted string. This is declared
* as a local string ("_proc_name) so that it can be also used by the function exit macros below.
*/
-#define ACPI_FUNCTION_NAME(a) struct acpi_debug_print_info _dbg; \
- _dbg.component_id = _COMPONENT; \
- _dbg.proc_name = a; \
- _dbg.module_name = _THIS_MODULE;
+#define ACPI_FUNCTION_NAME(a) struct acpi_debug_print_info _debug_info; \
+ _debug_info.component_id = _COMPONENT; \
+ _debug_info.proc_name = a; \
+ _debug_info.module_name = _THIS_MODULE;
#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace(__LINE__,&_dbg)
+ acpi_ut_trace(__LINE__,&_debug_info)
#define ACPI_FUNCTION_TRACE_PTR(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_ptr(__LINE__,&_dbg,(void *)b)
+ acpi_ut_trace_ptr(__LINE__,&_debug_info,(void *)b)
#define ACPI_FUNCTION_TRACE_U32(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_u32(__LINE__,&_dbg,(u32)b)
+ acpi_ut_trace_u32(__LINE__,&_debug_info,(u32)b)
#define ACPI_FUNCTION_TRACE_STR(a,b) ACPI_FUNCTION_NAME(a) \
- acpi_ut_trace_str(__LINE__,&_dbg,(char *)b)
+ acpi_ut_trace_str(__LINE__,&_debug_info,(char *)b)
#define ACPI_FUNCTION_ENTRY() acpi_ut_track_stack_ptr()
#define ACPI_DO_WHILE0(a) a
#endif
-#define return_VOID ACPI_DO_WHILE0 ({acpi_ut_exit(__LINE__,&_dbg);return;})
-#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({acpi_ut_status_exit(__LINE__,&_dbg,(s));return((s));})
-#define return_VALUE(s) ACPI_DO_WHILE0 ({acpi_ut_value_exit(__LINE__,&_dbg,(acpi_integer)(s));return((s));})
-#define return_PTR(s) ACPI_DO_WHILE0 ({acpi_ut_ptr_exit(__LINE__,&_dbg,(u8 *)(s));return((s));})
+#define return_VOID ACPI_DO_WHILE0 ({acpi_ut_exit(__LINE__,&_debug_info);return;})
+#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({acpi_ut_status_exit(__LINE__,&_debug_info,(s));return((s));})
+#define return_VALUE(s) ACPI_DO_WHILE0 ({acpi_ut_value_exit(__LINE__,&_debug_info,(acpi_integer)(s));return((s));})
+#define return_PTR(s) ACPI_DO_WHILE0 ({acpi_ut_ptr_exit(__LINE__,&_debug_info,(u8 *)(s));return((s));})
/* Conditional execution */
/* Stack and buffer dumping */
-#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand(a)
+#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand((a),0)
#define ACPI_DUMP_OPERANDS(a,b,c,d,e) acpi_ex_dump_operands(a,b,c,d,e,_THIS_MODULE,__LINE__)
#define ACPI_DUMP_ENTRY(a,b) acpi_ns_dump_entry (a,b)
+
+#ifdef ACPI_FUTURE_USAGE
#define ACPI_DUMP_TABLES(a,b) acpi_ns_dump_tables(a,b)
+#endif
+
#define ACPI_DUMP_PATHNAME(a,b,c,d) acpi_ns_dump_pathname(a,b,c,d)
#define ACPI_DUMP_RESOURCE_LIST(a) acpi_rs_dump_resource_list(a)
#define ACPI_DUMP_BUFFER(a,b) acpi_ut_dump_buffer((u8 *)a,b,DB_BYTE_DISPLAY,_COMPONENT)
#define ACPI_DUMP_STACK_ENTRY(a)
#define ACPI_DUMP_OPERANDS(a,b,c,d,e)
#define ACPI_DUMP_ENTRY(a,b)
+
+#ifdef ACPI_FUTURE_USAGE
#define ACPI_DUMP_TABLES(a,b)
+#endif
+
#define ACPI_DUMP_PATHNAME(a,b,c,d)
#define ACPI_DUMP_RESOURCE_LIST(a)
#define ACPI_DUMP_BUFFER(a,b)
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
-
-#define ACPI_GET_STACK_POINTER _asm {mov eax, ebx}
-
#endif /* ACMACROS_H */
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
u32 bit_length; /* Length of field in bits */\
u32 base_byte_offset; /* Byte offset within containing object */\
u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
- u8 datum_valid_bits; /* Valid bit in first "Field datum" */\
- u8 end_field_valid_bits; /* Valid bits in the last "field datum" */\
- u8 end_buffer_valid_bits; /* Valid bits in the last "buffer datum" */\
+ u8 access_bit_width; /* Read/Write size in bits (8-64) */\
u32 value; /* Value to store into the Bank or Index register */\
struct acpi_namespace_node *node; /* Link back to parent node */
acpi_integer value;
};
-
+/*
+ * Note: The String and Buffer object must be identical through the Pointer
+ * element. There is code that depends on this.
+ */
struct acpi_object_string /* Null terminated, ASCII characters only */
{
ACPI_OBJECT_COMMON_HEADER
};
-#define INFINITE_CONCURRENCY 0xFF
+#define ACPI_INFINITE_CONCURRENCY 0xFF
+
+typedef
+acpi_status (*ACPI_INTERNAL_METHOD) (
+ struct acpi_walk_state *walk_state);
struct acpi_object_method
{
u32 aml_length;
void *semaphore;
u8 *aml_start;
+ ACPI_INTERNAL_METHOD implementation;
u8 concurrency;
u8 thread_count;
acpi_owner_id owning_id;
struct acpi_object_mutex
{
ACPI_OBJECT_COMMON_HEADER
- u16 sync_level;
- u16 acquisition_depth;
- struct acpi_thread_state *owner_thread;
- void *semaphore;
+ u8 sync_level; /* 0-15, specified in Mutex() call */
+ u16 acquisition_depth; /* Allow multiple Acquires, same thread */
+ struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
+ void *semaphore; /* Actual OS synchronization object */
union acpi_operand_object *prev; /* Link for list of acquired mutexes */
union acpi_operand_object *next; /* Link for list of acquired mutexes */
- struct acpi_namespace_node *node; /* containing object */
+ struct acpi_namespace_node *node; /* Containing namespace node */
+ u8 original_sync_level; /* Owner's original sync level (0-15) */
};
u8 space_id;
union acpi_operand_object *handler; /* Handler for region access */
- struct acpi_namespace_node *node; /* containing object */
+ struct acpi_namespace_node *node; /* Containing namespace node */
union acpi_operand_object *next;
u32 length;
acpi_physical_address address;
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
/*
* Debug level macros that are used in the DEBUG_PRINT macros
*/
-#define ACPI_DEBUG_LEVEL(dl) (u32) dl,__LINE__,&_dbg
+#define ACPI_DEBUG_LEVEL(dl) (u32) dl,__LINE__,&_debug_info
/* Exception level -- used in the global "debug_level" */
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#ifndef __ACPI_BUS_H__
#define __ACPI_BUS_H__
-#if 0
-#include <xen/version.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,4))
-#include <xen/device.h>
-#define CONFIG_LDM
-#endif
-#endif /* 0 */
-
#include <acpi/acpi.h>
+#define PREFIX "ACPI: "
+
/* TBD: Make dynamic */
#define ACPI_MAX_HANDLES 10
struct acpi_handle_list {
#ifdef CONFIG_ACPI_BUS
-/*#include <xen/proc_fs.h>*/
+#include <linux/proc_fs.h>
#define ACPI_BUS_FILE_ROOT "acpi"
-/*extern struct proc_dir_entry *acpi_root_dir;*/
+extern struct proc_dir_entry *acpi_root_dir;
extern FADT_DESCRIPTOR acpi_fadt;
enum acpi_bus_removal_type {
typedef int (*acpi_op_resume) (struct acpi_device *device, int state);
typedef int (*acpi_op_scan) (struct acpi_device *device);
typedef int (*acpi_op_bind) (struct acpi_device *device);
+typedef int (*acpi_op_unbind) (struct acpi_device *device);
+typedef int (*acpi_op_match) (struct acpi_device *device,
+ struct acpi_driver *driver);
struct acpi_device_ops {
acpi_op_add add;
acpi_op_resume resume;
acpi_op_scan scan;
acpi_op_bind bind;
+ acpi_op_unbind unbind;
+ acpi_op_match match;
};
struct acpi_driver {
struct list_head node;
char name[80];
char class[80];
- int references;
+ atomic_t references;
char *ids; /* Supported Hardware IDs */
struct acpi_device_ops ops;
};
u32 suprise_removal_ok:1;
u32 power_manageable:1;
u32 performance_manageable:1;
- u32 reserved:21;
+ u32 wake_capable:1; /* Wakeup(_PRW) supported? */
+ u32 reserved:20;
};
u32 explicit_get:1; /* _PSC present? */
u32 power_resources:1; /* Power resources */
u32 inrush_current:1; /* Serialize Dx->D0 */
- u32 wake_capable:1; /* Wakeup supported? */
- u32 wake_enabled:1; /* Enabled for wakeup */
u32 power_removed:1; /* Optimize Dx->D0 */
- u32 reserved:26;
+ u32 reserved:28;
};
struct acpi_device_power_state {
struct acpi_device_perf_state *states;
};
+/* Wakeup Management */
+struct acpi_device_wakeup_flags {
+ u8 valid:1; /* Can successfully enable wakeup? */
+ u8 run_wake:1; /* Run-Wake GPE devices */
+};
+
+struct acpi_device_wakeup_state {
+ u8 enabled:1;
+ u8 active:1;
+};
+
+struct acpi_device_wakeup {
+ acpi_handle gpe_device;
+ acpi_integer gpe_number;;
+ acpi_integer sleep_state;
+ struct acpi_handle_list resources;
+ struct acpi_device_wakeup_state state;
+ struct acpi_device_wakeup_flags flags;
+};
/* Device */
struct acpi_device *parent;
struct list_head children;
struct list_head node;
+ struct list_head wakeup_list;
+ struct list_head g_list;
struct acpi_device_status status;
struct acpi_device_flags flags;
struct acpi_device_pnp pnp;
struct acpi_device_power power;
+ struct acpi_device_wakeup wakeup;
struct acpi_device_perf performance;
struct acpi_device_dir dir;
struct acpi_device_ops ops;
struct acpi_driver *driver;
void *driver_data;
-#ifdef CONFIG_LDM
- struct device dev;
-#endif
+ struct kobject kobj;
};
#define acpi_driver_data(d) ((d)->driver_data)
u32 data;
};
+extern struct subsystem acpi_subsys;
/*
* External Functions
*/
-int acpi_bus_get_device(acpi_handle, struct acpi_device **device);
+int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device);
+void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context);
int acpi_bus_get_status (struct acpi_device *device);
int acpi_bus_get_power (acpi_handle handle, int *state);
int acpi_bus_set_power (acpi_handle handle, int state);
int acpi_bus_receive_event (struct acpi_bus_event *event);
int acpi_bus_register_driver (struct acpi_driver *driver);
int acpi_bus_unregister_driver (struct acpi_driver *driver);
-int acpi_bus_scan (struct acpi_device *device);
-int acpi_init (void);
-void acpi_exit (void);
+int acpi_bus_scan (struct acpi_device *start);
+int acpi_bus_trim(struct acpi_device *start, int rmdevice);
+int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent,
+ acpi_handle handle, int type);
+
+int acpi_match_ids (struct acpi_device *device, char *ids);
+int acpi_create_dir(struct acpi_device *);
+void acpi_remove_dir(struct acpi_device *);
#endif /*CONFIG_ACPI_BUS*/
/*
- * acpi_drivers.h ($Revision: 32 $)
+ * acpi_drivers.h ($Revision: 31 $)
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
#define __ACPI_DRIVERS_H__
#include <xen/acpi.h>
-#include "acpi_bus.h"
+#include <acpi/acpi_bus.h>
#define ACPI_MAX_STRING 80
-
-/* --------------------------------------------------------------------------
- ACPI Bus
- -------------------------------------------------------------------------- */
-
#define ACPI_BUS_COMPONENT 0x00010000
-#define ACPI_BUS_CLASS "system_bus"
-#define ACPI_BUS_HID "ACPI_BUS"
-#define ACPI_BUS_DRIVER_NAME "ACPI Bus Driver"
-#define ACPI_BUS_DEVICE_NAME "System Bus"
-
-
-/* --------------------------------------------------------------------------
- AC Adapter
- -------------------------------------------------------------------------- */
-
-#define ACPI_AC_COMPONENT 0x00020000
-#define ACPI_AC_CLASS "ac_adapter"
-#define ACPI_AC_HID "ACPI0003"
-#define ACPI_AC_DRIVER_NAME "ACPI AC Adapter Driver"
-#define ACPI_AC_DEVICE_NAME "AC Adapter"
-#define ACPI_AC_FILE_STATE "state"
-#define ACPI_AC_NOTIFY_STATUS 0x80
-#define ACPI_AC_STATUS_OFFLINE 0x00
-#define ACPI_AC_STATUS_ONLINE 0x01
-#define ACPI_AC_STATUS_UNKNOWN 0xFF
-
-
-/* --------------------------------------------------------------------------
- Battery
- -------------------------------------------------------------------------- */
-
-#define ACPI_BATTERY_COMPONENT 0x00040000
-#define ACPI_BATTERY_CLASS "battery"
-#define ACPI_BATTERY_HID "PNP0C0A"
-#define ACPI_BATTERY_DRIVER_NAME "ACPI Battery Driver"
-#define ACPI_BATTERY_DEVICE_NAME "Battery"
-#define ACPI_BATTERY_FILE_INFO "info"
-#define ACPI_BATTERY_FILE_STATUS "state"
-#define ACPI_BATTERY_FILE_ALARM "alarm"
-#define ACPI_BATTERY_NOTIFY_STATUS 0x80
-#define ACPI_BATTERY_NOTIFY_INFO 0x81
-#define ACPI_BATTERY_UNITS_WATTS "mW"
-#define ACPI_BATTERY_UNITS_AMPS "mA"
-
-
-/* --------------------------------------------------------------------------
- Button
- -------------------------------------------------------------------------- */
+#define ACPI_SYSTEM_COMPONENT 0x02000000
-#define ACPI_BUTTON_COMPONENT 0x00080000
-#define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver"
-#define ACPI_BUTTON_CLASS "button"
-#define ACPI_BUTTON_FILE_INFO "info"
-#define ACPI_BUTTON_FILE_STATE "state"
-#define ACPI_BUTTON_TYPE_UNKNOWN 0x00
-#define ACPI_BUTTON_NOTIFY_STATUS 0x80
+/* _HID definitions */
-#define ACPI_BUTTON_SUBCLASS_POWER "power"
-#define ACPI_BUTTON_HID_POWER "PNP0C0C"
+#define ACPI_POWER_HID "ACPI_PWR"
+#define ACPI_PROCESSOR_HID "ACPI_CPU"
+#define ACPI_SYSTEM_HID "ACPI_SYS"
+#define ACPI_THERMAL_HID "ACPI_THM"
#define ACPI_BUTTON_HID_POWERF "ACPI_FPB"
-#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button (CM)"
-#define ACPI_BUTTON_DEVICE_NAME_POWERF "Power Button (FF)"
-#define ACPI_BUTTON_TYPE_POWER 0x01
-#define ACPI_BUTTON_TYPE_POWERF 0x02
-
-#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep"
-#define ACPI_BUTTON_HID_SLEEP "PNP0C0E"
#define ACPI_BUTTON_HID_SLEEPF "ACPI_FSB"
-#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button (CM)"
-#define ACPI_BUTTON_DEVICE_NAME_SLEEPF "Sleep Button (FF)"
-#define ACPI_BUTTON_TYPE_SLEEP 0x03
-#define ACPI_BUTTON_TYPE_SLEEPF 0x04
-
-#define ACPI_BUTTON_SUBCLASS_LID "lid"
-#define ACPI_BUTTON_HID_LID "PNP0C0D"
-#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch"
-#define ACPI_BUTTON_TYPE_LID 0x05
-
-
-/* --------------------------------------------------------------------------
- Embedded Controller
- -------------------------------------------------------------------------- */
-
-#define ACPI_EC_COMPONENT 0x00100000
-#define ACPI_EC_CLASS "embedded_controller"
-#define ACPI_EC_HID "PNP0C09"
-#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver"
-#define ACPI_EC_DEVICE_NAME "Embedded Controller"
-#define ACPI_EC_FILE_INFO "info"
-
-#ifdef CONFIG_ACPI_EC
-
-int acpi_ec_ecdt_probe (void);
-int acpi_ec_init (void);
-void acpi_ec_exit (void);
-
-#endif
-
-
-/* --------------------------------------------------------------------------
- Fan
- -------------------------------------------------------------------------- */
-
-#define ACPI_FAN_COMPONENT 0x00200000
-#define ACPI_FAN_CLASS "fan"
-#define ACPI_FAN_HID "PNP0C0B"
-#define ACPI_FAN_DRIVER_NAME "ACPI Fan Driver"
-#define ACPI_FAN_DEVICE_NAME "Fan"
-#define ACPI_FAN_FILE_STATE "state"
-#define ACPI_FAN_NOTIFY_STATUS 0x80
/* --------------------------------------------------------------------------
#define ACPI_PCI_COMPONENT 0x00400000
-/* ACPI PCI Root Bridge (pci_root.c) */
-
-#define ACPI_PCI_ROOT_CLASS "pci_bridge"
-#define ACPI_PCI_ROOT_HID "PNP0A03"
-#define ACPI_PCI_ROOT_DRIVER_NAME "ACPI PCI Root Bridge Driver"
-#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge"
-
-int acpi_pci_root_init (void);
-void acpi_pci_root_exit (void);
-
/* ACPI PCI Interrupt Link (pci_link.c) */
-#define ACPI_PCI_LINK_CLASS "pci_irq_routing"
-#define ACPI_PCI_LINK_HID "PNP0C0F"
-#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver"
-#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link"
-#define ACPI_PCI_LINK_FILE_INFO "info"
-#define ACPI_PCI_LINK_FILE_STATUS "state"
-
-int acpi_pci_link_check (void);
+int acpi_irq_penalty_init (void);
int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low);
-int acpi_pci_link_init (void);
-void acpi_pci_link_exit (void);
/* ACPI PCI Interrupt Routing (pci_irq.c) */
int acpi_pci_irq_add_prt (acpi_handle handle, int segment, int bus);
+void acpi_pci_irq_del_prt (int segment, int bus);
/* ACPI PCI Device Binding (pci_bind.c) */
struct pci_bus;
int acpi_pci_bind (struct acpi_device *device);
+int acpi_pci_unbind (struct acpi_device *device);
int acpi_pci_bind_root (struct acpi_device *device, struct acpi_pci_id *id, struct pci_bus *bus);
+/* Arch-defined function to add a bus to the system */
+
+struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, int bus);
+
#endif /*CONFIG_ACPI_PCI*/
Power Resource
-------------------------------------------------------------------------- */
-#define ACPI_POWER_COMPONENT 0x00800000
-#define ACPI_POWER_CLASS "power_resource"
-#define ACPI_POWER_HID "ACPI_PWR"
-#define ACPI_POWER_DRIVER_NAME "ACPI Power Resource Driver"
-#define ACPI_POWER_DEVICE_NAME "Power Resource"
-#define ACPI_POWER_FILE_INFO "info"
-#define ACPI_POWER_FILE_STATUS "state"
-#define ACPI_POWER_RESOURCE_STATE_OFF 0x00
-#define ACPI_POWER_RESOURCE_STATE_ON 0x01
-#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
-
#ifdef CONFIG_ACPI_POWER
-
+int acpi_enable_wakeup_device_power (struct acpi_device *dev);
+int acpi_disable_wakeup_device_power (struct acpi_device *dev);
int acpi_power_get_inferred_state (struct acpi_device *device);
int acpi_power_transition (struct acpi_device *device, int state);
-int acpi_power_init (void);
-void acpi_power_exit (void);
-
#endif
+/* --------------------------------------------------------------------------
+ Embedded Controller
+ -------------------------------------------------------------------------- */
+#ifdef CONFIG_ACPI_EC
+int acpi_ec_ecdt_probe (void);
+#endif
+
/* --------------------------------------------------------------------------
Processor
-------------------------------------------------------------------------- */
-#define ACPI_PROCESSOR_COMPONENT 0x01000000
-#define ACPI_PROCESSOR_CLASS "processor"
-#define ACPI_PROCESSOR_HID "ACPI_CPU"
-#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
-#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
-#define ACPI_PROCESSOR_FILE_INFO "info"
-#define ACPI_PROCESSOR_FILE_POWER "power"
-#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
-#define ACPI_PROCESSOR_FILE_THROTTLING "throttling"
-#define ACPI_PROCESSOR_FILE_LIMIT "limit"
-#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
-#define ACPI_PROCESSOR_NOTIFY_POWER 0x81
#define ACPI_PROCESSOR_LIMIT_NONE 0x00
#define ACPI_PROCESSOR_LIMIT_INCREMENT 0x01
#define ACPI_PROCESSOR_LIMIT_DECREMENT 0x02
int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
-/* --------------------------------------------------------------------------
- System
- -------------------------------------------------------------------------- */
-
-#define ACPI_SYSTEM_COMPONENT 0x02000000
-#define ACPI_SYSTEM_CLASS "system"
-#define ACPI_SYSTEM_HID "ACPI_SYS"
-#define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver"
-#define ACPI_SYSTEM_DEVICE_NAME "System"
-#define ACPI_SYSTEM_FILE_INFO "info"
-#define ACPI_SYSTEM_FILE_EVENT "event"
-#define ACPI_SYSTEM_FILE_ALARM "alarm"
-#define ACPI_SYSTEM_FILE_DSDT "dsdt"
-#define ACPI_SYSTEM_FILE_FADT "fadt"
-#define ACPI_SYSTEM_FILE_SLEEP "sleep"
-#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer"
-#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level"
-
-#ifdef CONFIG_ACPI_SYSTEM
-
-int acpi_system_init (void);
-void acpi_system_exit (void);
-
-#endif
-
-
-/* --------------------------------------------------------------------------
- Thermal Zone
- -------------------------------------------------------------------------- */
-
-#define ACPI_THERMAL_COMPONENT 0x04000000
-#define ACPI_THERMAL_CLASS "thermal_zone"
-#define ACPI_THERMAL_HID "ACPI_THM"
-#define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver"
-#define ACPI_THERMAL_DEVICE_NAME "Thermal Zone"
-#define ACPI_THERMAL_FILE_STATE "state"
-#define ACPI_THERMAL_FILE_TEMPERATURE "temperature"
-#define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points"
-#define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode"
-#define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency"
-#define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
-#define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81
-#define ACPI_THERMAL_NOTIFY_DEVICES 0x82
-#define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0
-#define ACPI_THERMAL_NOTIFY_HOT 0xF1
-#define ACPI_THERMAL_MODE_ACTIVE 0x00
-#define ACPI_THERMAL_MODE_PASSIVE 0x01
-#define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff"
-
-
-/* --------------------------------------------------------------------------
- Debug Support
- -------------------------------------------------------------------------- */
-
-#define ACPI_DEBUG_RESTORE 0
-#define ACPI_DEBUG_LOW 1
-#define ACPI_DEBUG_MEDIUM 2
-#define ACPI_DEBUG_HIGH 3
-#define ACPI_DEBUG_DRIVERS 4
-
-/*extern u32 acpi_dbg_level;*/
-/*extern u32 acpi_dbg_layer;*/
-
-static inline void
-acpi_set_debug (
- u32 flag)
-{
- static u32 layer_save;
- static u32 level_save;
-
- switch (flag) {
- case ACPI_DEBUG_RESTORE:
- acpi_dbg_layer = layer_save;
- acpi_dbg_level = level_save;
- break;
- case ACPI_DEBUG_LOW:
- case ACPI_DEBUG_MEDIUM:
- case ACPI_DEBUG_HIGH:
- case ACPI_DEBUG_DRIVERS:
- layer_save = acpi_dbg_layer;
- level_save = acpi_dbg_level;
- break;
- }
-
- switch (flag) {
- case ACPI_DEBUG_LOW:
- acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
- acpi_dbg_level = ACPI_DEBUG_DEFAULT;
- break;
- case ACPI_DEBUG_MEDIUM:
- acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
- acpi_dbg_level = ACPI_LV_FUNCTIONS | ACPI_LV_ALL_EXCEPTIONS;
- break;
- case ACPI_DEBUG_HIGH:
- acpi_dbg_layer = 0xFFFFFFFF;
- acpi_dbg_level = 0xFFFFFFFF;
- break;
- case ACPI_DEBUG_DRIVERS:
- acpi_dbg_layer = ACPI_ALL_DRIVERS;
- acpi_dbg_level = 0xFFFFFFFF;
- break;
- }
-}
-
-
#endif /*__ACPI_DRIVERS_H__*/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
acpi_os_map_memory (
acpi_physical_address physical_address,
acpi_size size,
- void **logical_address);
+ void __iomem **logical_address);
void
acpi_os_unmap_memory (
- void *logical_address,
+ void __iomem *logical_address,
acpi_size size);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_os_get_physical_address (
void *logical_address,
acpi_physical_address *physical_address);
+#endif
/*
acpi_status
acpi_os_install_interrupt_handler (
- u32 interrupt_number,
- OSD_HANDLER service_routine,
+ u32 gsi,
+ acpi_osd_handler service_routine,
void *context);
acpi_status
acpi_os_remove_interrupt_handler (
- u32 interrupt_number,
- OSD_HANDLER service_routine);
+ u32 gsi,
+ acpi_osd_handler service_routine);
/*
acpi_status
acpi_os_queue_for_execution (
u32 priority,
- OSD_EXECUTION_CALLBACK function,
+ acpi_osd_exec_callback function,
+ void *context);
+
+void
+acpi_os_wait_events_complete (
void *context);
void
acpi_os_sleep (
- u32 seconds,
- u32 milliseconds);
+ acpi_integer milliseconds);
void
acpi_os_stall (
/*
* Platform and hardware-independent PCI configuration space access
+ * Note: Can't use "Register" as a parameter, changed to "Reg" --
+ * certain compilers complain.
*/
acpi_status
acpi_os_read_pci_configuration (
struct acpi_pci_id *pci_id,
- u32 register,
+ u32 reg,
void *value,
u32 width);
acpi_status
acpi_os_write_pci_configuration (
struct acpi_pci_id *pci_id,
- u32 register,
+ u32 reg,
acpi_integer value,
u32 width);
/*
* Interim function needed for PCI IRQ routing
*/
+
void
acpi_os_derive_pci_id(
acpi_handle rhandle,
void *pointer,
acpi_size length);
+#ifdef ACPI_FUTURE_USAGE
u8
acpi_os_writable (
void *pointer,
acpi_size length);
+#endif
-u32
+u64
acpi_os_get_timer (
void);
* Debug input
*/
+#ifdef ACPI_FUTURE_USAGE
u32
acpi_os_get_line (
char *buffer);
+#endif
/*
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
acpi_terminate (
void);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_subsystem_status (
void);
+#endif
acpi_status
acpi_enable (
acpi_disable (
void);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_get_system_info (
struct acpi_buffer *ret_buffer);
+#endif
const char *
acpi_format_exception (
acpi_purge_cached_objects (
void);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_install_initialization_handler (
acpi_init_handler handler,
u32 function);
+#endif
/*
* ACPI Memory manager
acpi_load_tables (
void);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_load_table (
struct acpi_table_header *table_ptr);
acpi_table_type table_type,
u32 instance,
struct acpi_table_header *out_table_header);
+#endif /* ACPI_FUTURE_USAGE */
acpi_status
acpi_get_table (
struct acpi_object_list *parameter_objects,
struct acpi_buffer *return_object_buffer);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_evaluate_object_typed (
acpi_handle object,
struct acpi_object_list *external_params,
struct acpi_buffer *return_buffer,
acpi_object_type return_type);
+#endif
acpi_status
acpi_get_object_info (
acpi_handle gpe_device,
u32 gpe_number,
u32 type,
- acpi_gpe_handler handler,
+ acpi_event_handler address,
void *context);
+#ifdef ACPI_FUTURE_USAGE
+acpi_status
+acpi_install_exception_handler (
+ acpi_exception_handler handler);
+#endif
+
+
+/*
+ * Event interfaces
+ */
+
acpi_status
acpi_acquire_global_lock (
u16 timeout,
acpi_remove_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number,
- acpi_gpe_handler handler);
+ acpi_event_handler address);
acpi_status
acpi_enable_event (
acpi_clear_event (
u32 event);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_get_event_status (
u32 event,
acpi_event_status *event_status);
+#endif /* ACPI_FUTURE_USAGE */
+
+acpi_status
+acpi_set_gpe_type (
+ acpi_handle gpe_device,
+ u32 gpe_number,
+ u8 type);
acpi_status
acpi_enable_gpe (
u32 gpe_number,
u32 flags);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_get_gpe_status (
acpi_handle gpe_device,
u32 gpe_number,
u32 flags,
acpi_event_status *event_status);
+#endif /* ACPI_FUTURE_USAGE */
acpi_status
acpi_install_gpe_block (
acpi_handle device_handle,
struct acpi_buffer *ret_buffer);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_get_possible_resources(
acpi_handle device_handle,
struct acpi_buffer *ret_buffer);
+#endif
acpi_status
acpi_walk_resources (
acpi_set_firmware_waking_vector (
acpi_physical_address physical_address);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_get_firmware_waking_vector (
acpi_physical_address *physical_address);
+#endif
acpi_status
acpi_get_sleep_type_data (
acpi_enter_sleep_state_prep (
u8 sleep_state);
-acpi_status
+acpi_status asmlinkage
acpi_enter_sleep_state (
u8 sleep_state);
-acpi_status
+acpi_status asmlinkage
acpi_enter_sleep_state_s4bios (
void);
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
struct acpi_walk_state
{
u8 data_type; /* To differentiate various internal objs MUST BE FIRST!*/\
+ u8 walk_type;
acpi_owner_id owner_id; /* Owner of objects created during the walk */
u8 last_predicate; /* Result of last predicate */
+ u8 reserved; /* For alignment */
u8 current_result; /* */
u8 next_op_info; /* Info about next_op */
u8 num_operands; /* Stack pointer for Operands[] array */
u8 return_used;
- u8 walk_type;
u16 opcode; /* Current AML opcode */
u8 scope_depth;
u8 reserved1;
struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */
union acpi_operand_object **caller_return_desc;
union acpi_generic_state *control_state; /* List of control states (nested IFs) */
- struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */
+ struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */
+ struct acpi_gpe_event_info *gpe_event_info; /* Info for GPE (_Lxx/_Exx methods only */
struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */
struct acpi_namespace_node *method_call_node; /* Called method Node*/
union acpi_parse_object *method_call_op; /* method_call Op if running a method */
union acpi_parse_object *next_op; /* next op to be processed */
acpi_parse_downwards descending_callback;
acpi_parse_upwards ascending_callback;
- struct acpi_thread_state *acpi_thread;
+ struct acpi_thread_state *thread;
struct acpi_walk_state *next; /* Next walk_state in list */
};
};
+/* Internal method parameter list */
+
+struct acpi_parameter_info
+{
+ struct acpi_namespace_node *node;
+ union acpi_operand_object **parameters;
+ union acpi_operand_object *return_object;
+ u8 parameter_type;
+ u8 return_object_type;
+};
+
+/* Types for parameter_type above */
+
+#define ACPI_PARAM_ARGS 0
+#define ACPI_PARAM_GPE 1
+
+
#endif
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
};
-/*
- * High performance timer
- */
-struct hpet_table
-{
- ACPI_TABLE_HEADER_DEF
- u32 hardware_id;
- u32 base_address [3];
- u8 hpet_number;
- u16 clock_tick;
- u8 attributes;
-};
-
#pragma pack()
#include "actbl1.h" /* Acpi 1.0 table definitions */
#include "actbl2.h" /* Acpi 2.0 table definitions */
+extern u8 acpi_fadt_is_v1; /* is set to 1 if FADT is revision 1,
+ * needed for certain workarounds */
+
+#pragma pack(1)
+/*
+ * High performance timer
+ */
+struct hpet_table
+{
+ ACPI_TABLE_HEADER_DEF
+ u32 hardware_id;
+ struct acpi_generic_address base_address;
+ u8 hpet_number;
+ u16 clock_tick;
+ u8 attributes;
+};
+
+#pragma pack()
#endif /* __ACTBL_H__ */
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#define BAF_8042_KEYBOARD_CONTROLLER 0x0002
#define FADT2_REVISION_ID 3
+#define FADT2_MINUS_REVISION_ID 2
#pragma pack(1)
u8 address_space_id; /* Address space where struct or register exists. */
u8 register_bit_width; /* Size in bits of given register */
u8 register_bit_offset; /* Bit offset within the register */
- u8 reserved; /* Must be 0 */
+ u8 access_width; /* Minimum Access size (ACPI 3.0) */
u64 address; /* 64-bit address of struct or register */
};
+#define FADT_REV2_COMMON \
+ u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ \
+ u32 V1_dsdt; /* 32-bit physical address of DSDT */ \
+ u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ \
+ u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ \
+ u16 sci_int; /* System vector of SCI interrupt */ \
+ u32 smi_cmd; /* Port address of SMI command port */ \
+ u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ \
+ u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ \
+ u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ \
+ u8 pstate_cnt; /* Processor performance state control*/ \
+ u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ \
+ u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ \
+ u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ \
+ u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ \
+ u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ \
+ u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \
+ u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ \
+ u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ \
+ u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ \
+ u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ \
+ u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ \
+ u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ \
+ u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \
+ u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ \
+ u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ \
+ u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ \
+ u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ \
+ u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ \
+ u16 flush_size; /* Number of flush strides that need to be read */ \
+ u16 flush_stride; /* Processor's memory cache line width, in bytes */ \
+ u8 duty_offset; /* Processor's duty cycle index in processor's P_CNT reg*/ \
+ u8 duty_width; /* Processor's duty cycle value bit width in P_CNT register.*/ \
+ u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ \
+ u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ \
+ u8 century; /* Index to century in RTC CMOS RAM */ \
+ u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/
+
/*
* ACPI 2.0 Fixed ACPI Description Table (FADT)
*/
struct fadt_descriptor_rev2
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */
- u32 V1_dsdt; /* 32-bit physical address of DSDT */
- u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/
- u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */
- u16 sci_int; /* System vector of SCI interrupt */
- u32 smi_cmd; /* Port address of SMI command port */
- u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */
- u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */
- u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
- u8 pstate_cnt; /* Processor performance state control*/
- u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
- u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
- u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
- u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
- u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
- u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
- u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
- u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
- u8 pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
- u8 pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
- u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
- u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */
- u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
- u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
- u8 gpe1_base; /* Offset in gpe model where gpe1 events start */
- u8 cst_cnt; /* Support for the _CST object and C States change notification.*/
- u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
- u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
- u16 flush_size; /* Number of flush strides that need to be read */
- u16 flush_stride; /* Processor's memory cache line width, in bytes */
- u8 duty_offset; /* Processor's duty cycle index in processor's P_CNT reg*/
- u8 duty_width; /* Processor's duty cycle value bit width in P_CNT register.*/
- u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
- u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
- u8 century; /* Index to century in RTC CMOS RAM */
- u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/
+ FADT_REV2_COMMON
u8 reserved2; /* Reserved */
u32 wb_invd : 1; /* The wbinvd instruction works properly */
u32 wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */
};
+/* "Downrevved" ACPI 2.0 FADT descriptor */
+
+struct fadt_descriptor_rev2_minus
+{
+ ACPI_TABLE_HEADER_DEF /* ACPI common table header */
+ FADT_REV2_COMMON
+ u8 reserved2; /* Reserved */
+ u32 flags;
+ struct acpi_generic_address reset_register; /* Reset register address in GAS format */
+ u8 reset_value; /* Value to write to the reset_register port to reset the system. */
+ u8 reserved7[3]; /* These three bytes must be zero */
+};
+
+
/* Embedded Controller */
struct ec_boot_resources
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
typedef u32 acpi_integer;
#define ACPI_INTEGER_MAX ACPI_UINT32_MAX
#define ACPI_INTEGER_BIT_SIZE 32
-#define ACPI_MAX_DECIMAL_DIGITS 10
+#define ACPI_MAX_DECIMAL_DIGITS 10 /* 2^32 = 4,294,967,296 */
#define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 32-bit divide */
typedef u64 acpi_integer;
#define ACPI_INTEGER_MAX ACPI_UINT64_MAX
#define ACPI_INTEGER_BIT_SIZE 64
-#define ACPI_MAX_DECIMAL_DIGITS 19
+#define ACPI_MAX_DECIMAL_DIGITS 20 /* 2^64 = 18,446,744,073,709,551,616 */
+
#if ACPI_MACHINE_WIDTH == 64
#define ACPI_USE_NATIVE_DIVIDE /* Use compiler native 64-bit divide */
#endif
#endif
+#define ACPI_MAX64_DECIMAL_DIGITS 20
+#define ACPI_MAX32_DECIMAL_DIGITS 10
+#define ACPI_MAX16_DECIMAL_DIGITS 5
+#define ACPI_MAX8_DECIMAL_DIGITS 3
/*
* Constants with special meanings
/*
* Power state values
*/
-
#define ACPI_STATE_UNKNOWN (u8) 0xFF
#define ACPI_STATE_S0 (u8) 0
#define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6
#define ACPI_NOTIFY_POWER_FAULT (u8) 7
-
/*
* Table types. These values are passed to the table related APIs
*/
#define ACPI_TABLE_MAX 6
#define NUM_ACPI_TABLE_TYPES (ACPI_TABLE_MAX+1)
-
/*
* Types associated with ACPI names and objects. The first group of
* values (up to ACPI_TYPE_EXTERNAL_MAX) correspond to the definition
* of the ACPI object_type() operator (See the ACPI Spec). Therefore,
* only add to the first group if the spec changes.
*
- * Types must be kept in sync with the global acpi_ns_properties
+ * NOTE: Types must be kept in sync with the global acpi_ns_properties
* and acpi_ns_type_names arrays.
*/
typedef u32 acpi_object_type;
#define ACPI_TYPE_LOCAL_INDEX_FIELD 0x13
#define ACPI_TYPE_LOCAL_REFERENCE 0x14 /* Arg#, Local#, Name, Debug, ref_of, Index */
#define ACPI_TYPE_LOCAL_ALIAS 0x15
-#define ACPI_TYPE_LOCAL_NOTIFY 0x16
-#define ACPI_TYPE_LOCAL_ADDRESS_HANDLER 0x17
-#define ACPI_TYPE_LOCAL_RESOURCE 0x18
-#define ACPI_TYPE_LOCAL_RESOURCE_FIELD 0x19
-#define ACPI_TYPE_LOCAL_SCOPE 0x1A /* 1 Name, multiple object_list Nodes */
+#define ACPI_TYPE_LOCAL_METHOD_ALIAS 0x16
+#define ACPI_TYPE_LOCAL_NOTIFY 0x17
+#define ACPI_TYPE_LOCAL_ADDRESS_HANDLER 0x18
+#define ACPI_TYPE_LOCAL_RESOURCE 0x19
+#define ACPI_TYPE_LOCAL_RESOURCE_FIELD 0x1A
+#define ACPI_TYPE_LOCAL_SCOPE 0x1B /* 1 Name, multiple object_list Nodes */
-#define ACPI_TYPE_NS_NODE_MAX 0x1A /* Last typecode used within a NS Node */
+#define ACPI_TYPE_NS_NODE_MAX 0x1B /* Last typecode used within a NS Node */
/*
* These are special object types that never appear in
* a Namespace node, only in an union acpi_operand_object
*/
-#define ACPI_TYPE_LOCAL_EXTRA 0x1B
-#define ACPI_TYPE_LOCAL_DATA 0x1C
+#define ACPI_TYPE_LOCAL_EXTRA 0x1C
+#define ACPI_TYPE_LOCAL_DATA 0x1D
-#define ACPI_TYPE_LOCAL_MAX 0x1C
+#define ACPI_TYPE_LOCAL_MAX 0x1D
/* All types above here are invalid */
-#define ACPI_TYPE_INVALID 0x1D
+#define ACPI_TYPE_INVALID 0x1E
#define ACPI_TYPE_NOT_FOUND 0xFF
#define ACPI_WRITE 1
#define ACPI_IO_MASK 1
-
/*
- * Acpi Event Types: Fixed & General Purpose
+ * Event Types: Fixed & General Purpose
*/
typedef u32 acpi_event_type;
#define ACPI_EVENT_MAX 4
#define ACPI_NUM_FIXED_EVENTS ACPI_EVENT_MAX + 1
-#define ACPI_GPE_INVALID 0xFF
-#define ACPI_GPE_MAX 0xFF
-#define ACPI_NUM_GPE 256
-
-#define ACPI_EVENT_LEVEL_TRIGGERED 1
-#define ACPI_EVENT_EDGE_TRIGGERED 2
-
-/*
- * Flags for GPE and Lock interfaces
- */
-#define ACPI_EVENT_WAKE_ENABLE 0x2
-#define ACPI_EVENT_WAKE_DISABLE 0x2
-
-#define ACPI_NOT_ISR 0x1
-#define ACPI_ISR 0x0
-
-
/*
- * acpi_event Status:
+ * Event Status - Per event
* -------------
* The encoding of acpi_event_status is illustrated below.
* Note that a set bit (1) indicates the property is TRUE
#define ACPI_EVENT_FLAG_WAKE_ENABLED (acpi_event_status) 0x02
#define ACPI_EVENT_FLAG_SET (acpi_event_status) 0x04
+/*
+ * General Purpose Events (GPE)
+ */
+#define ACPI_GPE_INVALID 0xFF
+#define ACPI_GPE_MAX 0xFF
+#define ACPI_NUM_GPE 256
+
+#define ACPI_GPE_ENABLE 0
+#define ACPI_GPE_DISABLE 1
+
+
+/*
+ * GPE info flags - Per GPE
+ * +-+-+-+---+---+-+
+ * |7|6|5|4:3|2:1|0|
+ * +-+-+-+---+---+-+
+ * | | | | | |
+ * | | | | | +--- Interrupt type: Edge or Level Triggered
+ * | | | | +--- Type: Wake-only, Runtime-only, or wake/runtime
+ * | | | +--- Type of dispatch -- to method, handler, or none
+ * | | +--- Enabled for runtime?
+ * | +--- Enabled for wake?
+ * +--- System state when GPE ocurred (running/waking)
+ */
+#define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x01
+#define ACPI_GPE_LEVEL_TRIGGERED (u8) 0x01
+#define ACPI_GPE_EDGE_TRIGGERED (u8) 0x00
+
+#define ACPI_GPE_TYPE_MASK (u8) 0x06
+#define ACPI_GPE_TYPE_WAKE_RUN (u8) 0x06
+#define ACPI_GPE_TYPE_WAKE (u8) 0x02
+#define ACPI_GPE_TYPE_RUNTIME (u8) 0x04 /* Default */
+
+#define ACPI_GPE_DISPATCH_MASK (u8) 0x18
+#define ACPI_GPE_DISPATCH_HANDLER (u8) 0x08
+#define ACPI_GPE_DISPATCH_METHOD (u8) 0x10
+#define ACPI_GPE_DISPATCH_NOT_USED (u8) 0x00 /* Default */
+
+#define ACPI_GPE_RUN_ENABLE_MASK (u8) 0x20
+#define ACPI_GPE_RUN_ENABLED (u8) 0x20
+#define ACPI_GPE_RUN_DISABLED (u8) 0x00 /* Default */
+
+#define ACPI_GPE_WAKE_ENABLE_MASK (u8) 0x40
+#define ACPI_GPE_WAKE_ENABLED (u8) 0x40
+#define ACPI_GPE_WAKE_DISABLED (u8) 0x00 /* Default */
+
+#define ACPI_GPE_ENABLE_MASK (u8) 0x60 /* Both run/wake */
+
+#define ACPI_GPE_SYSTEM_MASK (u8) 0x80
+#define ACPI_GPE_SYSTEM_RUNNING (u8) 0x80
+#define ACPI_GPE_SYSTEM_WAKING (u8) 0x00
+
+/*
+ * Flags for GPE and Lock interfaces
+ */
+#define ACPI_EVENT_WAKE_ENABLE 0x2 /* acpi_gpe_enable */
+#define ACPI_EVENT_WAKE_DISABLE 0x2 /* acpi_gpe_disable */
+
+#define ACPI_NOT_ISR 0x1
+#define ACPI_ISR 0x0
+
/* Notify types */
-#define ACPI_SYSTEM_NOTIFY 0
-#define ACPI_DEVICE_NOTIFY 1
-#define ACPI_MAX_NOTIFY_HANDLER_TYPE 1
+#define ACPI_SYSTEM_NOTIFY 0x1
+#define ACPI_DEVICE_NOTIFY 0x2
+#define ACPI_ALL_NOTIFY 0x3
+#define ACPI_MAX_NOTIFY_HANDLER_TYPE 0x3
#define ACPI_MAX_SYS_NOTIFY 0x7f
*/
typedef u32
-(ACPI_SYSTEM_XFACE *OSD_HANDLER) (
+(ACPI_SYSTEM_XFACE *acpi_osd_handler) (
void *context);
typedef void
-(ACPI_SYSTEM_XFACE *OSD_EXECUTION_CALLBACK) (
+(ACPI_SYSTEM_XFACE *acpi_osd_exec_callback) (
void *context);
/*
u32 (*acpi_event_handler) (
void *context);
-typedef
-void (*acpi_gpe_handler) (
- void *context);
-
typedef
void (*acpi_notify_handler) (
acpi_handle device,
#define ACPI_INIT_DEVICE_INI 1
+typedef
+acpi_status (*acpi_exception_handler) (
+ acpi_status aml_status,
+ acpi_name name,
+ u16 opcode,
+ u32 aml_offset,
+ void *context);
+
-/* Address Spaces (Operation Regions */
+/* Address Spaces (For Operation Regions) */
typedef
acpi_status (*acpi_adr_space_handler) (
#define ACPI_VALID_HID 0x0004
#define ACPI_VALID_UID 0x0008
#define ACPI_VALID_CID 0x0010
+#define ACPI_VALID_SXDS 0x0020
#define ACPI_COMMON_OBJ_INFO \
{
ACPI_COMMON_OBJ_INFO;
- u32 valid; /* Indicates which fields are valid */
+ u32 valid; /* Indicates which fields below are valid */
u32 current_status; /* _STA value */
acpi_integer address; /* _ADR value if any */
struct acpi_device_id hardware_id; /* _HID value if any */
struct acpi_device_id unique_id; /* _UID value if any */
+ u8 highest_dstates[4]; /* _sx_d values: 0xFF indicates not valid */
struct acpi_compatible_id_list compatibility_id; /* List of _CIDs if any */
};
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
union acpi_generic_state *state,
void *context);
-
acpi_status
acpi_ut_walk_package_tree (
union acpi_operand_object *source_object,
acpi_pkg_callback walk_callback,
void *context);
-
struct acpi_pkg_info
{
u8 *free_space;
const char *src_string,
acpi_size count);
+int
+acpi_ut_memcmp (
+ const char *buffer1,
+ const char *buffer2,
+ acpi_size count);
+
int
acpi_ut_strncmp (
const char *string1,
#define METHOD_NAME__PRT "_PRT"
#define METHOD_NAME__CRS "_CRS"
#define METHOD_NAME__PRS "_PRS"
+#define METHOD_NAME__PRW "_PRW"
+acpi_status
+acpi_ut_osi_implementation (
+ struct acpi_walk_state *walk_state);
+
acpi_status
acpi_ut_evaluate_object (
struct acpi_namespace_node *prefix_node,
struct acpi_namespace_node *device_node,
struct acpi_device_id *uid);
+acpi_status
+acpi_ut_execute_sxds (
+ struct acpi_namespace_node *device_node,
+ u8 *highest);
/*
* ut_mutex - mutual exclusion interfaces
acpi_ut_create_buffer_object (
acpi_size buffer_size);
+union acpi_operand_object *
+acpi_ut_create_string_object (
+ acpi_size string_size);
+
/*
* ut_ref_cnt - Object reference count management
u16 action,
union acpi_generic_state **state_list);
+#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_ut_create_pkg_state_and_push (
void *internal_object,
void *external_object,
u16 index,
union acpi_generic_state **state_list);
+#endif
union acpi_generic_state *
acpi_ut_create_control_state (
acpi_ut_delete_generic_state (
union acpi_generic_state *state);
+#ifdef ACPI_ENABLE_OBJECT_CACHE
void
acpi_ut_delete_generic_state_cache (
void);
void
acpi_ut_delete_object_cache (
void);
+#endif
/*
* utmisc
acpi_status
acpi_ut_divide (
- acpi_integer *in_dividend,
- acpi_integer *in_divisor,
+ acpi_integer in_dividend,
+ acpi_integer in_divisor,
acpi_integer *out_quotient,
acpi_integer *out_remainder);
acpi_status
acpi_ut_short_divide (
- acpi_integer *in_dividend,
+ acpi_integer in_dividend,
u32 divisor,
acpi_integer *out_quotient,
u32 *out_remainder);
u32 base,
acpi_integer *ret_integer);
+/* Values for Base above (16=Hex, 10=Decimal) */
+
+#define ACPI_ANY_BASE 0
+
+#ifdef ACPI_FUTURE_USAGE
char *
acpi_ut_strupr (
char *src_string);
+#endif
u8 *
acpi_ut_get_resource_end_tag (
u32 list_id,
void *object);
+#ifdef ACPI_ENABLE_OBJECT_CACHE
void
acpi_ut_delete_generic_cache (
u32 list_id);
+#endif
acpi_status
acpi_ut_validate_buffer (
char *module,
u32 line);
+#ifdef ACPI_FUTURE_USAGE
void
acpi_ut_dump_allocation_info (
void);
+#endif
void
acpi_ut_dump_allocations (
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#define ACPI_DISASSEMBLER
#define ACPI_NO_METHOD_EXECUTION
#define ACPI_USE_SYSTEM_CLIBRARY
+#define ACPI_ENABLE_OBJECT_CACHE
#endif
#ifdef _ACPI_EXEC_APP
#define ACPI_DEBUGGER
#define ACPI_DISASSEMBLER
#define ACPI_USE_SYSTEM_CLIBRARY
+#define ACPI_ENABLE_OBJECT_CACHE
#endif
#ifdef _ACPI_ASL_COMPILER
#define ACPI_DISASSEMBLER
#define ACPI_CONSTANT_EVAL_ONLY
#define ACPI_USE_SYSTEM_CLIBRARY
+#define ACPI_ENABLE_OBJECT_CACHE
#endif
/*
#define COMPILER_DEPENDENT_INT64 long long
#define COMPILER_DEPENDENT_UINT64 unsigned long long
-
-/* Name of host operating system (returned by the _OS_ namespace object) */
-
-#define ACPI_OS_NAME "Intel ACPI/CA Core Subsystem"
-
-/* This macro is used to tag functions as "printf-like" because
+/*
+ * This macro is used to tag functions as "printf-like" because
* some compilers can catch printf format string problems. MSVC
* doesn't, so this is proprocessed away.
*/
*/
#define ACPI_STRSTR(s1,s2) strstr((s1), (s2))
+
+#ifdef ACPI_FUTURE_USAGE
#define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s))
+#endif
+
#define ACPI_STRLEN(s) (acpi_size) strlen((s))
#define ACPI_STRCPY(d,s) (void) strcpy((d), (s))
#define ACPI_STRNCPY(d,s,n) (void) strncpy((d), (s), (acpi_size)(n))
#define ACPI_STRCAT(d,s) (void) strcat((d), (s))
#define ACPI_STRNCAT(d,s,n) strncat((d), (s), (acpi_size)(n))
#define ACPI_STRTOUL(d,s,n) strtoul((d), (s), (acpi_size)(n))
+#define ACPI_MEMCMP(s1,s2,n) memcmp((s1), (s2), (acpi_size)(n))
#define ACPI_MEMCPY(d,s,n) (void) memcpy((d), (s), (acpi_size)(n))
#define ACPI_MEMSET(d,s,n) (void) memset((d), (s), (acpi_size)(n))
#define ACPI_STRSTR(s1,s2) acpi_ut_strstr ((s1), (s2))
+
+#ifdef ACPI_FUTURE_USAGE
#define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s))
+#endif
+
#define ACPI_STRLEN(s) (acpi_size) acpi_ut_strlen ((s))
#define ACPI_STRCPY(d,s) (void) acpi_ut_strcpy ((d), (s))
#define ACPI_STRNCPY(d,s,n) (void) acpi_ut_strncpy ((d), (s), (acpi_size)(n))
#define ACPI_STRCAT(d,s) (void) acpi_ut_strcat ((d), (s))
#define ACPI_STRNCAT(d,s,n) acpi_ut_strncat ((d), (s), (acpi_size)(n))
#define ACPI_STRTOUL(d,s,n) acpi_ut_strtoul ((d), (s), (acpi_size)(n))
+#define ACPI_MEMCMP(s1,s2,n) acpi_ut_memcmp((s1), (s2), (acpi_size)(n))
#define ACPI_MEMCPY(d,s,n) (void) acpi_ut_memcpy ((d), (s), (acpi_size)(n))
#define ACPI_MEMSET(d,v,n) (void) acpi_ut_memset ((d), (v), (acpi_size)(n))
#define ACPI_TOUPPER acpi_ut_to_upper
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* to to tell the compiler warning in a per-variable manner that a variable
* is unused.
*/
-#define ACPI_UNUSED_VAR __attribute_used__
+#define ACPI_UNUSED_VAR __attribute__ ((unused))
#endif /* __ACGCC_H__ */
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2005, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#ifndef __ACLINUX_H__
#define __ACLINUX_H__
-#define ACPI_OS_NAME "Linux"
-
#define ACPI_USE_SYSTEM_CLIBRARY
#define ACPI_USE_DO_WHILE_0
#define ACPI_USE_NATIVE_DIVIDE
#endif
+#define __cdecl
+#define ACPI_FLUSH_CPU_CACHE()
#endif /* __KERNEL__ */
/* Linux uses GCC */
#define touch_nmi_watchdog()
// from linux/include/linux/types.h
-#define BITS_TO_LONGS(bits) \
- (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
-#define DECLARE_BITMAP(name,bits) \
- unsigned long name[BITS_TO_LONGS(bits)]
#define CLEAR_BITMAP(name,bits) \
memset(name, 0, BITS_TO_LONGS(bits)*sizeof(unsigned long))
//#define __kernel
//#define __safe
#define __force
-#define __iomem
#define __chk_user_ptr(x) (void)0
//#define __chk_io_ptr(x) (void)0
//#define __builtin_warning(x, y...) (1)
//#define CONFIG_NR_CPUS 16
#define barrier() __asm__ __volatile__("": : :"memory")
-// linux/include/spinlock.h
-#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
-
///////////////////////////////////////////////////////////////
// xen/include/asm/config.h
// Natural boundary upon TR size to define xenheap space
#define __ASM_APIC_H
#include <xen/config.h>
-#include <asm/regs.h>
+#include <asm/fixmap.h>
#include <asm/apicdef.h>
#include <asm/system.h>
-#ifdef CONFIG_X86_LOCAL_APIC
+#define Dprintk(x...)
+
+/*
+ * Debugging macros
+ */
+#define APIC_QUIET 0
+#define APIC_VERBOSE 1
+#define APIC_DEBUG 2
-#define APIC_DEBUG 0
+extern int apic_verbosity;
-#if APIC_DEBUG
-#define Dprintk(x...) printk(x)
-#else
-#define Dprintk(x...)
-#endif
+/*
+ * Define the default level of output to be very little
+ * This can be turned up by using apic=verbose for more
+ * information and apic=debug for _lots_ of information.
+ * apic_verbosity is defined in apic.c
+ */
+#define apic_printk(v, s, a...) do { \
+ if ((v) <= apic_verbosity) \
+ printk(s, ##a); \
+ } while (0)
+
+
+#ifdef CONFIG_X86_LOCAL_APIC
/*
* Basic functions accessing APICs.
static __inline__ void apic_wait_icr_idle(void)
{
- do { } while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY );
+ while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY )
+ cpu_relax();
}
+int get_physical_broadcast(void);
+
#ifdef CONFIG_X86_GOOD_APIC
# define FORCE_READ_AROUND_WRITE 0
# define apic_read_around(x)
apic_write_around(APIC_EOI, 0);
}
+extern void (*wait_timer_tick)(void);
+
extern int get_maxlvt(void);
extern void clear_local_APIC(void);
extern void connect_bsp_APIC (void);
extern void disconnect_bsp_APIC (void);
extern void disable_local_APIC (void);
+extern void lapic_shutdown (void);
extern int verify_local_APIC (void);
extern void cache_APIC_registers (void);
extern void sync_Arb_IDs (void);
extern void init_bsp_APIC (void);
extern void setup_local_APIC (void);
extern void init_apic_mappings (void);
-extern void smp_local_timer_interrupt (struct cpu_user_regs * regs);
-extern void setup_APIC_clocks (void);
+extern void smp_local_timer_interrupt (struct cpu_user_regs *regs);
+extern void setup_boot_APIC_clock (void);
+extern void setup_secondary_APIC_clock (void);
extern void setup_apic_nmi_watchdog (void);
-extern void nmi_watchdog_tick (struct cpu_user_regs * regs);
+extern int reserve_lapic_nmi(void);
+extern void release_lapic_nmi(void);
+extern void disable_timer_nmi_watchdog(void);
+extern void enable_timer_nmi_watchdog(void);
+extern void nmi_watchdog_tick (struct cpu_user_regs *regs);
extern void touch_nmi_watchdog(void);
extern int APIC_init_uniprocessor (void);
extern void disable_APIC_timer(void);
extern unsigned int watchdog_on;
extern int check_nmi_watchdog (void);
+extern void enable_NMI_through_LVT0 (void * dummy);
extern unsigned int nmi_watchdog;
#define NMI_NONE 0
#define NMI_LOCAL_APIC 2
#define NMI_INVALID 3
-#endif /* CONFIG_X86_LOCAL_APIC */
+#else /* !CONFIG_X86_LOCAL_APIC */
+static inline void lapic_shutdown(void) { }
+
+#endif /* !CONFIG_X86_LOCAL_APIC */
#endif /* __ASM_APIC_H */
#define APIC_DEFAULT_PHYS_BASE 0xfee00000
#define APIC_ID 0x20
-#define APIC_ID_MASK (0x0F<<24)
-#define GET_APIC_ID(x) (((x)>>24)&0x0F)
#define APIC_LVR 0x30
#define APIC_LVR_MASK 0xFF00FF
#define GET_APIC_VERSION(x) ((x)&0xFF)
#define GET_APIC_MAXLVT(x) (((x)>>16)&0xFF)
#define APIC_INTEGRATED(x) ((x)&0xF0)
-#define APIC_XAPIC_SUPPORT(x) ((x)>=0x14)
#define APIC_TASKPRI 0x80
#define APIC_TPRI_MASK 0xFF
#define APIC_ARBPRI 0x90
#define SET_APIC_LOGICAL_ID(x) (((x)<<24))
#define APIC_ALL_CPUS 0xFF
#define APIC_DFR 0xE0
-#define APIC_DFR_CLUSTER 0x0FFFFFFFul /* Clustered */
-#define APIC_DFR_FLAT 0xFFFFFFFFul /* Flat mode */
+#define APIC_DFR_CLUSTER 0x0FFFFFFFul
+#define APIC_DFR_FLAT 0xFFFFFFFFul
#define APIC_SPIV 0xF0
#define APIC_SPIV_FOCUS_DISABLED (1<<9)
#define APIC_SPIV_APIC_ENABLED (1<<8)
#define APIC_INT_LEVELTRIG 0x08000
#define APIC_INT_ASSERT 0x04000
#define APIC_ICR_BUSY 0x01000
-#define APIC_DEST_PHYSICAL 0x00000
#define APIC_DEST_LOGICAL 0x00800
#define APIC_DM_FIXED 0x00000
#define APIC_DM_LOWEST 0x00100
#define GET_APIC_DEST_FIELD(x) (((x)>>24)&0xFF)
#define SET_APIC_DEST_FIELD(x) ((x)<<24)
#define APIC_LVTT 0x320
+#define APIC_LVTTHMR 0x330
#define APIC_LVTPC 0x340
#define APIC_LVT0 0x350
#define APIC_LVT_TIMER_BASE_MASK (0x3<<18)
#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
-#ifdef CONFIG_X86_CLUSTERED_APIC
-#define MAX_IO_APICS 32
+#ifdef CONFIG_NUMA
+ #define MAX_IO_APICS 32
#else
-#define MAX_IO_APICS 8
+ #define MAX_IO_APICS 8
#endif
-
/*
- * The broadcast ID is 0xF for old APICs and 0xFF for xAPICs. SAPICs
- * don't broadcast (yet?), but if they did, they might use 0xFFFF.
+ * the local APIC register structure, memory mapped. Not terribly well
+ * tested, but we might eventually use this one in the future - the
+ * problem why we cannot use it right now is the P5 APIC, it has an
+ * errata which cannot take 8-bit reads and writes, only 32-bit ones ...
*/
-#define APIC_BROADCAST_ID_XAPIC (0xFF)
-#define APIC_BROADCAST_ID_APIC (0x0F)
+#define u32 unsigned int
+
+#define lapic ((volatile struct local_apic *)APIC_BASE)
+
+#ifndef __ASSEMBLY__
+struct local_apic {
+
+/*000*/ struct { u32 __reserved[4]; } __reserved_01;
+
+/*010*/ struct { u32 __reserved[4]; } __reserved_02;
+
+/*020*/ struct { /* APIC ID Register */
+ u32 __reserved_1 : 24,
+ phys_apic_id : 4,
+ __reserved_2 : 4;
+ u32 __reserved[3];
+ } id;
+
+/*030*/ const
+ struct { /* APIC Version Register */
+ u32 version : 8,
+ __reserved_1 : 8,
+ max_lvt : 8,
+ __reserved_2 : 8;
+ u32 __reserved[3];
+ } version;
+
+/*040*/ struct { u32 __reserved[4]; } __reserved_03;
+
+/*050*/ struct { u32 __reserved[4]; } __reserved_04;
+
+/*060*/ struct { u32 __reserved[4]; } __reserved_05;
+
+/*070*/ struct { u32 __reserved[4]; } __reserved_06;
+
+/*080*/ struct { /* Task Priority Register */
+ u32 priority : 8,
+ __reserved_1 : 24;
+ u32 __reserved_2[3];
+ } tpr;
+
+/*090*/ const
+ struct { /* Arbitration Priority Register */
+ u32 priority : 8,
+ __reserved_1 : 24;
+ u32 __reserved_2[3];
+ } apr;
+
+/*0A0*/ const
+ struct { /* Processor Priority Register */
+ u32 priority : 8,
+ __reserved_1 : 24;
+ u32 __reserved_2[3];
+ } ppr;
+
+/*0B0*/ struct { /* End Of Interrupt Register */
+ u32 eoi;
+ u32 __reserved[3];
+ } eoi;
+
+/*0C0*/ struct { u32 __reserved[4]; } __reserved_07;
+
+/*0D0*/ struct { /* Logical Destination Register */
+ u32 __reserved_1 : 24,
+ logical_dest : 8;
+ u32 __reserved_2[3];
+ } ldr;
+
+/*0E0*/ struct { /* Destination Format Register */
+ u32 __reserved_1 : 28,
+ model : 4;
+ u32 __reserved_2[3];
+ } dfr;
+
+/*0F0*/ struct { /* Spurious Interrupt Vector Register */
+ u32 spurious_vector : 8,
+ apic_enabled : 1,
+ focus_cpu : 1,
+ __reserved_2 : 22;
+ u32 __reserved_3[3];
+ } svr;
+
+/*100*/ struct { /* In Service Register */
+/*170*/ u32 bitfield;
+ u32 __reserved[3];
+ } isr [8];
+
+/*180*/ struct { /* Trigger Mode Register */
+/*1F0*/ u32 bitfield;
+ u32 __reserved[3];
+ } tmr [8];
+
+/*200*/ struct { /* Interrupt Request Register */
+/*270*/ u32 bitfield;
+ u32 __reserved[3];
+ } irr [8];
+
+/*280*/ union { /* Error Status Register */
+ struct {
+ u32 send_cs_error : 1,
+ receive_cs_error : 1,
+ send_accept_error : 1,
+ receive_accept_error : 1,
+ __reserved_1 : 1,
+ send_illegal_vector : 1,
+ receive_illegal_vector : 1,
+ illegal_register_address : 1,
+ __reserved_2 : 24;
+ u32 __reserved_3[3];
+ } error_bits;
+ struct {
+ u32 errors;
+ u32 __reserved_3[3];
+ } all_errors;
+ } esr;
+
+/*290*/ struct { u32 __reserved[4]; } __reserved_08;
+
+/*2A0*/ struct { u32 __reserved[4]; } __reserved_09;
+
+/*2B0*/ struct { u32 __reserved[4]; } __reserved_10;
+
+/*2C0*/ struct { u32 __reserved[4]; } __reserved_11;
+
+/*2D0*/ struct { u32 __reserved[4]; } __reserved_12;
+
+/*2E0*/ struct { u32 __reserved[4]; } __reserved_13;
+
+/*2F0*/ struct { u32 __reserved[4]; } __reserved_14;
+
+/*300*/ struct { /* Interrupt Command Register 1 */
+ u32 vector : 8,
+ delivery_mode : 3,
+ destination_mode : 1,
+ delivery_status : 1,
+ __reserved_1 : 1,
+ level : 1,
+ trigger : 1,
+ __reserved_2 : 2,
+ shorthand : 2,
+ __reserved_3 : 12;
+ u32 __reserved_4[3];
+ } icr1;
+
+/*310*/ struct { /* Interrupt Command Register 2 */
+ union {
+ u32 __reserved_1 : 24,
+ phys_dest : 4,
+ __reserved_2 : 4;
+ u32 __reserved_3 : 24,
+ logical_dest : 8;
+ } dest;
+ u32 __reserved_4[3];
+ } icr2;
+
+/*320*/ struct { /* LVT - Timer */
+ u32 vector : 8,
+ __reserved_1 : 4,
+ delivery_status : 1,
+ __reserved_2 : 3,
+ mask : 1,
+ timer_mode : 1,
+ __reserved_3 : 14;
+ u32 __reserved_4[3];
+ } lvt_timer;
+
+/*330*/ struct { /* LVT - Thermal Sensor */
+ u32 vector : 8,
+ delivery_mode : 3,
+ __reserved_1 : 1,
+ delivery_status : 1,
+ __reserved_2 : 3,
+ mask : 1,
+ __reserved_3 : 15;
+ u32 __reserved_4[3];
+ } lvt_thermal;
+
+/*340*/ struct { /* LVT - Performance Counter */
+ u32 vector : 8,
+ delivery_mode : 3,
+ __reserved_1 : 1,
+ delivery_status : 1,
+ __reserved_2 : 3,
+ mask : 1,
+ __reserved_3 : 15;
+ u32 __reserved_4[3];
+ } lvt_pc;
+
+/*350*/ struct { /* LVT - LINT0 */
+ u32 vector : 8,
+ delivery_mode : 3,
+ __reserved_1 : 1,
+ delivery_status : 1,
+ polarity : 1,
+ remote_irr : 1,
+ trigger : 1,
+ mask : 1,
+ __reserved_2 : 15;
+ u32 __reserved_3[3];
+ } lvt_lint0;
+
+/*360*/ struct { /* LVT - LINT1 */
+ u32 vector : 8,
+ delivery_mode : 3,
+ __reserved_1 : 1,
+ delivery_status : 1,
+ polarity : 1,
+ remote_irr : 1,
+ trigger : 1,
+ mask : 1,
+ __reserved_2 : 15;
+ u32 __reserved_3[3];
+ } lvt_lint1;
+
+/*370*/ struct { /* LVT - Error */
+ u32 vector : 8,
+ __reserved_1 : 4,
+ delivery_status : 1,
+ __reserved_2 : 3,
+ mask : 1,
+ __reserved_3 : 15;
+ u32 __reserved_4[3];
+ } lvt_error;
+
+/*380*/ struct { /* Timer Initial Count Register */
+ u32 initial_count;
+ u32 __reserved_2[3];
+ } timer_icr;
+
+/*390*/ const
+ struct { /* Timer Current Count Register */
+ u32 curr_count;
+ u32 __reserved_2[3];
+ } timer_ccr;
+
+/*3A0*/ struct { u32 __reserved[4]; } __reserved_16;
+
+/*3B0*/ struct { u32 __reserved[4]; } __reserved_17;
+
+/*3C0*/ struct { u32 __reserved[4]; } __reserved_18;
+
+/*3D0*/ struct { u32 __reserved[4]; } __reserved_19;
+
+/*3E0*/ struct { /* Timer Divide Configuration Register */
+ u32 divisor : 4,
+ __reserved_1 : 28;
+ u32 __reserved_2[3];
+ } timer_dcr;
+
+/*3F0*/ struct { u32 __reserved[4]; } __reserved_20;
+
+} __attribute__ ((packed));
+#endif /* !__ASSEMBLY__ */
+
+#undef u32
#endif
#if defined(__x86_64__)
+#define CONFIG_X86_64 1
+
#define asmlinkage
#define XENHEAP_DEFAULT_MB (16)
#elif defined(__i386__)
+#define CONFIG_X86_32 1
+
#define asmlinkage __attribute__((regparm(0)))
/*
#ifndef __ASM_DOMAIN_H__
#define __ASM_DOMAIN_H__
+#include <xen/config.h>
#include <xen/mm.h>
+#include <asm/vmx_vmcs.h>
struct trap_bounce {
unsigned long error_code;
#define _ASM_FIXMAP_H
#include <xen/config.h>
+#include <xen/lib.h>
#include <asm/acpi.h>
#include <asm/apicdef.h>
#include <asm/page.h>
#define set_fixmap_nocache(idx, phys) \
__set_fixmap(idx, phys, PAGE_HYPERVISOR_NOCACHE)
-#define fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+extern void __this_fixmap_does_not_exist(void);
+
+/*
+ * 'index to address' translation. If anyone tries to use the idx
+ * directly without translation, we catch the bug with a NULL-deference
+ * kernel oops. Illegal ranges of incoming indices are caught too.
+ */
+static always_inline unsigned long fix_to_virt(const unsigned int idx)
+{
+ /*
+ * This branch gets completely eliminated after inlining, except when
+ * someone tries to use fixaddr indices in an illegal way (such as mixing
+ * up address types or using out-of-range indices).
+ *
+ * If it doesn't get removed, the linker will complain loudly with a
+ * reasonably clear error message.
+ */
+ if (idx >= __end_of_fixed_addresses)
+ __this_fixmap_does_not_exist();
+
+ return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+ BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+ return __virt_to_fix(vaddr);
+}
#endif
#define __ASM_IO_APIC_H
#include <xen/config.h>
-#include <xen/types.h>
+#include <asm/fixmap.h>
+#include <asm/types.h>
#include <asm/mpspec.h>
/*
#ifdef CONFIG_X86_IO_APIC
-#define APIC_MISMATCH_DEBUG
+#ifdef CONFIG_PCI_MSI
+static inline int use_pci_vector(void) {return 1;}
+static inline void disable_edge_ioapic_vector(unsigned int vector) { }
+static inline void mask_and_ack_level_ioapic_vector(unsigned int vector) { }
+static inline void end_edge_ioapic_vector (unsigned int vector) { }
+#define startup_level_ioapic startup_level_ioapic_vector
+#define shutdown_level_ioapic mask_IO_APIC_vector
+#define enable_level_ioapic unmask_IO_APIC_vector
+#define disable_level_ioapic mask_IO_APIC_vector
+#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_vector
+#define end_level_ioapic end_level_ioapic_vector
+#define set_ioapic_affinity set_ioapic_affinity_vector
+
+#define startup_edge_ioapic startup_edge_ioapic_vector
+#define shutdown_edge_ioapic disable_edge_ioapic_vector
+#define enable_edge_ioapic unmask_IO_APIC_vector
+#define disable_edge_ioapic disable_edge_ioapic_vector
+#define ack_edge_ioapic ack_edge_ioapic_vector
+#define end_edge_ioapic end_edge_ioapic_vector
+#else
+static inline int use_pci_vector(void) {return 0;}
+static inline void disable_edge_ioapic_irq(unsigned int irq) { }
+static inline void mask_and_ack_level_ioapic_irq(unsigned int irq) { }
+static inline void end_edge_ioapic_irq (unsigned int irq) { }
+#define startup_level_ioapic startup_level_ioapic_irq
+#define shutdown_level_ioapic mask_IO_APIC_irq
+#define enable_level_ioapic unmask_IO_APIC_irq
+#define disable_level_ioapic mask_IO_APIC_irq
+#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_irq
+#define end_level_ioapic end_level_ioapic_irq
+#define set_ioapic_affinity set_ioapic_affinity_irq
+
+#define startup_edge_ioapic startup_edge_ioapic_irq
+#define shutdown_edge_ioapic disable_edge_ioapic_irq
+#define enable_edge_ioapic unmask_IO_APIC_irq
+#define disable_edge_ioapic disable_edge_ioapic_irq
+#define ack_edge_ioapic ack_edge_ioapic_irq
+#define end_edge_ioapic end_edge_ioapic_irq
+#endif
#define IO_APIC_BASE(idx) \
- ((volatile int *)(fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \
+ ((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \
+ (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK)))
/*
* The structure of the IO-APIC:
*/
-struct IO_APIC_reg_00 {
- __u32 __reserved_2 : 14,
- LTS : 1,
- delivery_type : 1,
- __reserved_1 : 8,
- ID : 4,
- __reserved_0 : 4;
-} __attribute__ ((packed));
+union IO_APIC_reg_00 {
+ u32 raw;
+ struct {
+ u32 __reserved_2 : 14,
+ LTS : 1,
+ delivery_type : 1,
+ __reserved_1 : 8,
+ ID : 8;
+ } __attribute__ ((packed)) bits;
+};
-struct IO_APIC_reg_01 {
- __u32 version : 8,
- __reserved_2 : 7,
- PRQ : 1,
- entries : 8,
- __reserved_1 : 8;
-} __attribute__ ((packed));
+union IO_APIC_reg_01 {
+ u32 raw;
+ struct {
+ u32 version : 8,
+ __reserved_2 : 7,
+ PRQ : 1,
+ entries : 8,
+ __reserved_1 : 8;
+ } __attribute__ ((packed)) bits;
+};
-struct IO_APIC_reg_02 {
- __u32 __reserved_2 : 24,
- arbitration : 4,
- __reserved_1 : 4;
-} __attribute__ ((packed));
+union IO_APIC_reg_02 {
+ u32 raw;
+ struct {
+ u32 __reserved_2 : 24,
+ arbitration : 4,
+ __reserved_1 : 4;
+ } __attribute__ ((packed)) bits;
+};
-struct IO_APIC_reg_03 {
- __u32 boot_DT : 1,
- __reserved_1 : 31;
-} __attribute__ ((packed));
+union IO_APIC_reg_03 {
+ u32 raw;
+ struct {
+ u32 boot_DT : 1,
+ __reserved_1 : 31;
+ } __attribute__ ((packed)) bits;
+};
/*
* # of IO-APICs and # of IRQ routing registers
extern int mp_irq_entries;
/* MP IRQ source entries */
-extern struct mpc_config_intsrc *mp_irqs;
+extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* non-0 if default (table-less) MP configuration */
extern int mpc_default_type;
}
/*
- * Synchronize the IO-APIC and the CPU by doing
- * a dummy read from the IO-APIC
+ * Re-write a value: to be used for read-modify-write
+ * cycles where the read already set up the index register.
+ *
+ * Older SiS APIC requires we rewrite the index regiser
*/
-static inline void io_apic_sync(unsigned int apic)
+#define sis_apic_bug 0 /* This may need propagating from domain0. */
+static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
{
- (void) *(IO_APIC_BASE(apic)+4);
+ if (sis_apic_bug)
+ *IO_APIC_BASE(apic) = reg;
+ *(IO_APIC_BASE(apic)+4) = value;
}
+/* 1 if "noapic" boot option passed */
+extern int skip_ioapic_setup;
+
/*
* If we use the IO-APIC for IRQ routing, disable automatic
* assignment of PCI IRQ's.
*/
-#define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup)
+#define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
#ifdef CONFIG_ACPI_BOOT
extern int io_apic_get_unique_id (int ioapic, int apic_id);
extern int io_apic_get_version (int ioapic);
extern int io_apic_get_redir_entries (int ioapic);
extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low);
-#endif
-
-extern int skip_ioapic_setup; /* 1 for "noapic" */
-
-static inline void disable_ioapic_setup(void)
-{
- skip_ioapic_setup = 1;
-}
-
-static inline int ioapic_setup_disabled(void)
-{
- return skip_ioapic_setup;
-}
+#endif /*CONFIG_ACPI_BOOT*/
-extern int assign_irq_vector(int irq);
+extern int (*ioapic_renumber_irq)(int ioapic, int irq);
-#else /* !CONFIG_X86_IO_APIC */
+#else /* !CONFIG_X86_IO_APIC */
#define io_apic_assign_pci_irqs 0
+#endif
-static inline void disable_ioapic_setup(void)
-{ }
-
-#endif /* !CONFIG_X86_IO_APIC */
+extern int assign_irq_vector(int irq);
#endif
+++ /dev/null
-/*
- * based on linux-2.6.10/include/asm-i386/mach-default/io_ports.h
- *
- * Machine specific IO port address definition for generic.
- * Written by Osamu Tomita <tomita@cinet.co.jp>
- */
-#ifndef _MACH_IO_PORTS_H
-#define _MACH_IO_PORTS_H
-
-/* i8253A PIT registers */
-#define PIT_MODE 0x43
-#define PIT_CH0 0x40
-#define PIT_CH2 0x42
-
-/* i8259A PIC registers */
-#define PIC_MASTER_CMD 0x20
-#define PIC_MASTER_IMR 0x21
-#define PIC_MASTER_ISR PIC_MASTER_CMD
-#define PIC_MASTER_POLL PIC_MASTER_ISR
-#define PIC_MASTER_OCW3 PIC_MASTER_ISR
-#define PIC_SLAVE_CMD 0xa0
-#define PIC_SLAVE_IMR 0xa1
-
-/* i8259A PIC related value */
-#define PIC_CASCADE_IR 2
-#define MASTER_ICW4_DEFAULT 0x01
-#define SLAVE_ICW4_DEFAULT 0x01
-#define PIC_ICW4_AEOI 2
-
-#endif /* !_MACH_IO_PORTS_H */
#include <xen/config.h>
#include <asm/atomic.h>
#include <asm/asm_defns.h>
+#include <irq_vectors.h>
extern void disable_irq(unsigned int);
extern void disable_irq_nosync(unsigned int);
extern void enable_irq(unsigned int);
-/*
- * IDT vectors usable for external interrupt sources start
- * at 0x20:
- */
-#define FIRST_EXTERNAL_VECTOR 0x30
-
-#define NR_IRQS (256 - FIRST_EXTERNAL_VECTOR)
-
-#define HYPERCALL_VECTOR 0x82
-
-/*
- * Vectors 0x30-0x3f are used for ISA interrupts.
- */
-
-/*
- * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
- */
-#define SPURIOUS_APIC_VECTOR 0xff
-#define ERROR_APIC_VECTOR 0xfe
-#define INVALIDATE_TLB_VECTOR 0xfd
-#define EVENT_CHECK_VECTOR 0xfc
-#define CALL_FUNCTION_VECTOR 0xfb
-#define KDB_VECTOR 0xfa
-
-/*
- * Local APIC timer IRQ vector is on a different priority level,
- * to work around the 'lost local interrupt if more than 2 IRQ
- * sources per level' errata.
- */
-#define LOCAL_TIMER_VECTOR 0xef
-
-/*
- * First APIC vector available to drivers: (vectors 0x40-0xee)
- * we start at 0x41 to spread out vectors evenly between priority
- * levels. (0x82 is the hypercall vector)
- */
-#define FIRST_DEVICE_VECTOR 0x41
-#define FIRST_SYSTEM_VECTOR 0xef
-
-extern int irq_vector[NR_IRQS];
+extern u8 irq_vector[NR_IRQ_VECTORS];
#define IO_APIC_VECTOR(irq) irq_vector[irq]
+#define AUTO_ASSIGN -1
+
+extern void (*interrupt[NR_IRQS])(void);
-/*
- * Various low-level irq details needed by irq.c, process.c,
- * time.c, io_apic.c and smp.c
- *
- * Interrupt entry/exit code at both C and assembly level
- */
+#define platform_legacy_irq(irq) ((irq) < 16)
extern void mask_irq(unsigned int irq);
extern void unmask_irq(unsigned int irq);
--- /dev/null
+/*
+ * include/asm-i386/mach-default/apm.h
+ *
+ * Machine specific APM BIOS functions for generic.
+ * Split out from apm.c by Osamu Tomita <tomita@cinet.co.jp>
+ */
+
+#ifndef _ASM_APM_H
+#define _ASM_APM_H
+
+#ifdef APM_ZERO_SEGS
+# define APM_DO_ZERO_SEGS \
+ "pushl %%ds\n\t" \
+ "pushl %%es\n\t" \
+ "xorl %%edx, %%edx\n\t" \
+ "mov %%dx, %%ds\n\t" \
+ "mov %%dx, %%es\n\t" \
+ "mov %%dx, %%fs\n\t" \
+ "mov %%dx, %%gs\n\t"
+# define APM_DO_POP_SEGS \
+ "popl %%es\n\t" \
+ "popl %%ds\n\t"
+#else
+# define APM_DO_ZERO_SEGS
+# define APM_DO_POP_SEGS
+#endif
+
+static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in,
+ u32 *eax, u32 *ebx, u32 *ecx,
+ u32 *edx, u32 *esi)
+{
+ /*
+ * N.B. We do NOT need a cld after the BIOS call
+ * because we always save and restore the flags.
+ */
+ __asm__ __volatile__(APM_DO_ZERO_SEGS
+ "pushl %%edi\n\t"
+ "pushl %%ebp\n\t"
+ "lcall *%%cs:apm_bios_entry\n\t"
+ "setc %%al\n\t"
+ "popl %%ebp\n\t"
+ "popl %%edi\n\t"
+ APM_DO_POP_SEGS
+ : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx),
+ "=S" (*esi)
+ : "a" (func), "b" (ebx_in), "c" (ecx_in)
+ : "memory", "cc");
+}
+
+static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in,
+ u32 ecx_in, u32 *eax)
+{
+ int cx, dx, si;
+ u8 error;
+
+ /*
+ * N.B. We do NOT need a cld after the BIOS call
+ * because we always save and restore the flags.
+ */
+ __asm__ __volatile__(APM_DO_ZERO_SEGS
+ "pushl %%edi\n\t"
+ "pushl %%ebp\n\t"
+ "lcall *%%cs:apm_bios_entry\n\t"
+ "setc %%bl\n\t"
+ "popl %%ebp\n\t"
+ "popl %%edi\n\t"
+ APM_DO_POP_SEGS
+ : "=a" (*eax), "=b" (error), "=c" (cx), "=d" (dx),
+ "=S" (si)
+ : "a" (func), "b" (ebx_in), "c" (ecx_in)
+ : "memory", "cc");
+ return error;
+}
+
+#endif /* _ASM_APM_H */
--- /dev/null
+#ifndef _MACH_BIOS_EBDA_H
+#define _MACH_BIOS_EBDA_H
+
+/*
+ * there is a real-mode segmented pointer pointing to the
+ * 4K EBDA area at 0x40E.
+ */
+static inline unsigned int get_bios_ebda(void)
+{
+ unsigned int address = *(unsigned short *)phys_to_virt(0x40E);
+ address <<= 4;
+ return address; /* 0 means none */
+}
+
+#endif /* _MACH_BIOS_EBDA_H */
--- /dev/null
+/* defines for inline arch setup functions */
+
+#include <asm/apic.h>
+
+/**
+ * do_timer_interrupt_hook - hook into timer tick
+ * @regs: standard registers from interrupt
+ *
+ * Description:
+ * This hook is called immediately after the timer interrupt is ack'd.
+ * It's primary purpose is to allow architectures that don't possess
+ * individual per CPU clocks (like the CPU APICs supply) to broadcast the
+ * timer interrupt as a means of triggering reschedules etc.
+ **/
+
+static inline void do_timer_interrupt_hook(struct pt_regs *regs)
+{
+ do_timer(regs);
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(regs));
+#endif
+/*
+ * In the SMP case we use the local APIC timer interrupt to do the
+ * profiling, except when we simulate SMP mode on a uniprocessor
+ * system, in that case we have to call the local interrupt handler.
+ */
+#ifndef CONFIG_X86_LOCAL_APIC
+ profile_tick(CPU_PROFILING, regs);
+#else
+ if (!using_apic_timer)
+ smp_local_timer_interrupt(regs);
+#endif
+}
+
+
+/* you can safely undefine this if you don't have the Neptune chipset */
+
+#define BUGGY_NEPTUN_TIMER
+
+/**
+ * do_timer_overflow - process a detected timer overflow condition
+ * @count: hardware timer interrupt count on overflow
+ *
+ * Description:
+ * This call is invoked when the jiffies count has not incremented but
+ * the hardware timer interrupt has. It means that a timer tick interrupt
+ * came along while the previous one was pending, thus a tick was missed
+ **/
+static inline int do_timer_overflow(int count)
+{
+ int i;
+
+ spin_lock(&i8259A_lock);
+ /*
+ * This is tricky when I/O APICs are used;
+ * see do_timer_interrupt().
+ */
+ i = inb(0x20);
+ spin_unlock(&i8259A_lock);
+
+ /* assumption about timer being IRQ0 */
+ if (i & 0x01) {
+ /*
+ * We cannot detect lost timer interrupts ...
+ * well, that's why we call them lost, don't we? :)
+ * [hmm, on the Pentium and Alpha we can ... sort of]
+ */
+ count -= LATCH;
+ } else {
+#ifdef BUGGY_NEPTUN_TIMER
+ /*
+ * for the Neptun bug we know that the 'latch'
+ * command doesn't latch the high and low value
+ * of the counter atomically. Thus we have to
+ * substract 256 from the counter
+ * ... funny, isnt it? :)
+ */
+
+ count -= 256;
+#else
+ printk("do_slow_gettimeoffset(): hardware timer problem?\n");
+#endif
+ }
+ return count;
+}
--- /dev/null
+/*
+ * This file is designed to contain the BUILD_INTERRUPT specifications for
+ * all of the extra named interrupt vectors used by the architecture.
+ * Usually this is the Inter Process Interrupts (IPIs)
+ */
+
+/*
+ * The following vectors are part of the Linux architecture, there
+ * is no hardware IRQ pin equivalent for them, they are triggered
+ * through the ICC by us (IPIs)
+ */
+#ifdef CONFIG_X86_SMP
+BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
+BUILD_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
+BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
+#endif
+
+/*
+ * every pentium local APIC has two 'local interrupts', with a
+ * soft-definable vector attached to both interrupts, one of
+ * which is a timer interrupt, the other one is error counter
+ * overflow. Linux uses the local APIC timer interrupt to get
+ * a much simpler SMP time architecture:
+ */
+#ifdef CONFIG_X86_LOCAL_APIC
+BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
+BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
+BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
+
+#ifdef CONFIG_X86_MCE_P4THERMAL
+BUILD_INTERRUPT(thermal_interrupt,THERMAL_APIC_VECTOR)
+#endif
+
+#endif
--- /dev/null
+/*
+ * arch/i386/mach-generic/io_ports.h
+ *
+ * Machine specific IO port address definition for generic.
+ * Written by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef _MACH_IO_PORTS_H
+#define _MACH_IO_PORTS_H
+
+/* i8253A PIT registers */
+#define PIT_MODE 0x43
+#define PIT_CH0 0x40
+#define PIT_CH2 0x42
+
+/* i8259A PIC registers */
+#define PIC_MASTER_CMD 0x20
+#define PIC_MASTER_IMR 0x21
+#define PIC_MASTER_ISR PIC_MASTER_CMD
+#define PIC_MASTER_POLL PIC_MASTER_ISR
+#define PIC_MASTER_OCW3 PIC_MASTER_ISR
+#define PIC_SLAVE_CMD 0xa0
+#define PIC_SLAVE_IMR 0xa1
+
+/* i8259A PIC related value */
+#define PIC_CASCADE_IR 2
+#define MASTER_ICW4_DEFAULT 0x01
+#define SLAVE_ICW4_DEFAULT 0x01
+#define PIC_ICW4_AEOI 2
+
+#endif /* !_MACH_IO_PORTS_H */
--- /dev/null
+/*
+ * This file should contain #defines for all of the interrupt vector
+ * numbers used by this architecture.
+ *
+ * In addition, there are some standard defines:
+ *
+ * FIRST_EXTERNAL_VECTOR:
+ * The first free place for external interrupts
+ *
+ * SYSCALL_VECTOR:
+ * The IRQ vector a syscall makes the user to kernel transition
+ * under.
+ *
+ * TIMER_IRQ:
+ * The IRQ number the timer interrupt comes in at.
+ *
+ * NR_IRQS:
+ * The total number of interrupt vectors (including all the
+ * architecture specific interrupts) needed.
+ *
+ */
+#ifndef _ASM_IRQ_VECTORS_H
+#define _ASM_IRQ_VECTORS_H
+
+/*
+ * IDT vectors usable for external interrupt sources start
+ * at 0x20:
+ */
+#define FIRST_EXTERNAL_VECTOR 0x20
+
+#define HYPERCALL_VECTOR 0x82
+
+/*
+ * Vectors 0x20-0x2f are used for ISA interrupts.
+ */
+
+/*
+ * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
+ *
+ * some of the following vectors are 'rare', they are merged
+ * into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
+ * TLB, reschedule and local APIC vectors are performance-critical.
+ *
+ * Vectors 0xf0-0xfa are free (reserved for future Linux use).
+ */
+#define SPURIOUS_APIC_VECTOR 0xff
+#define ERROR_APIC_VECTOR 0xfe
+#define INVALIDATE_TLB_VECTOR 0xfd
+#define EVENT_CHECK_VECTOR 0xfc
+#define CALL_FUNCTION_VECTOR 0xfb
+
+#define THERMAL_APIC_VECTOR 0xf0
+/*
+ * Local APIC timer IRQ vector is on a different priority level,
+ * to work around the 'lost local interrupt if more than 2 IRQ
+ * sources per level' errata.
+ */
+#define LOCAL_TIMER_VECTOR 0xef
+
+/*
+ * First APIC vector available to drivers: (vectors 0x30-0xee)
+ * we start at 0x31 to spread out vectors evenly between priority
+ * levels. (0x80 is the syscall vector)
+ */
+#define FIRST_DEVICE_VECTOR 0x31
+#define FIRST_SYSTEM_VECTOR 0xef
+
+#define TIMER_IRQ 0
+
+/*
+ * 16 8259A IRQ's, 208 potential APIC interrupt sources.
+ * Right now the APIC is mostly only used for SMP.
+ * 256 vectors is an architectural limit. (we can have
+ * more than 256 devices theoretically, but they will
+ * have to use shared interrupts)
+ * Since vectors 0x00-0x1f are used/reserved for the CPU,
+ * the usable vector space is 0x20-0xff (224 vectors)
+ */
+
+/*
+ * The maximum number of vectors supported by i386 processors
+ * is limited to 256. For processors other than i386, NR_VECTORS
+ * should be changed accordingly.
+ */
+#define NR_VECTORS 256
+
+#include "irq_vectors_limits.h"
+
+#define FPU_IRQ 13
+
+#define FIRST_VM86_IRQ 3
+#define LAST_VM86_IRQ 15
+#define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15)
+
+
+#endif /* _ASM_IRQ_VECTORS_H */
--- /dev/null
+#ifndef _ASM_IRQ_VECTORS_LIMITS_H
+#define _ASM_IRQ_VECTORS_LIMITS_H
+
+#ifdef CONFIG_PCI_MSI
+#define NR_IRQS FIRST_SYSTEM_VECTOR
+#define NR_IRQ_VECTORS NR_IRQS
+#else
+#ifdef CONFIG_X86_IO_APIC
+#define NR_IRQS 224
+# if (224 >= 32 * NR_CPUS)
+# define NR_IRQ_VECTORS NR_IRQS
+# else
+# define NR_IRQ_VECTORS (32 * NR_CPUS)
+# endif
+#else
+#define NR_IRQS 16
+#define NR_IRQ_VECTORS NR_IRQS
+#endif
+#endif
+
+#endif /* _ASM_IRQ_VECTORS_LIMITS_H */
--- /dev/null
+#ifndef __ASM_MACH_APIC_H
+#define __ASM_MACH_APIC_H
+
+#include <mach_apicdef.h>
+#include <asm/smp.h>
+
+#define APIC_DFR_VALUE (APIC_DFR_FLAT)
+
+static inline cpumask_t target_cpus(void)
+{
+#ifdef CONFIG_SMP
+ return cpu_online_map;
+#else
+ return cpumask_of_cpu(0);
+#endif
+}
+#define TARGET_CPUS (target_cpus())
+
+#define NO_BALANCE_IRQ (0)
+#define esr_disable (0)
+
+#define NO_IOAPIC_CHECK (0)
+
+#define INT_DELIVERY_MODE dest_LowestPrio
+#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */
+
+static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
+{
+ return physid_isset(apicid, bitmap);
+}
+
+static inline unsigned long check_apicid_present(int bit)
+{
+ return physid_isset(bit, phys_cpu_present_map);
+}
+
+/*
+ * Set up the logical destination ID.
+ *
+ * Intel recommends to set DFR, LDR and TPR before enabling
+ * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
+ * document number 292116). So here it goes...
+ */
+static inline void init_apic_ldr(void)
+{
+ unsigned long val;
+
+ apic_write_around(APIC_DFR, APIC_DFR_VALUE);
+ val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
+ val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
+ apic_write_around(APIC_LDR, val);
+}
+
+static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
+{
+ return phys_map;
+}
+
+static inline void clustered_apic_check(void)
+{
+ printk("Enabling APIC mode: %s. Using %d I/O APICs\n",
+ "Flat", nr_ioapics);
+}
+
+static inline int multi_timer_check(int apic, int irq)
+{
+ return 0;
+}
+
+static inline int apicid_to_node(int logical_apicid)
+{
+ return 0;
+}
+
+/* Mapping from cpu number to logical apicid */
+static inline int cpu_to_logical_apicid(int cpu)
+{
+ return 1 << cpu;
+}
+
+static inline int cpu_present_to_apicid(int mps_cpu)
+{
+ if (mps_cpu < get_physical_broadcast())
+ return mps_cpu;
+ else
+ return BAD_APICID;
+}
+
+static inline physid_mask_t apicid_to_cpu_present(int phys_apicid)
+{
+ return physid_mask_of_physid(phys_apicid);
+}
+
+static inline int mpc_apic_id(struct mpc_config_processor *m,
+ struct mpc_config_translation *translation_record)
+{
+ printk("Processor #%d %d:%d APIC version %d\n",
+ m->mpc_apicid,
+ (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+ (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+ m->mpc_apicver);
+ return (m->mpc_apicid);
+}
+
+static inline void setup_portio_remap(void)
+{
+}
+
+static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
+{
+ return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map);
+}
+
+static inline int apic_id_registered(void)
+{
+ return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map);
+}
+
+static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
+{
+ return cpus_addr(cpumask)[0];
+}
+
+static inline void enable_apic_mode(void)
+{
+}
+
+static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
+{
+ return cpuid_apic >> index_msb;
+}
+
+#endif /* __ASM_MACH_APIC_H */
--- /dev/null
+#ifndef __ASM_MACH_APICDEF_H
+#define __ASM_MACH_APICDEF_H
+
+#define APIC_ID_MASK (0xF<<24)
+
+static inline unsigned get_apic_id(unsigned long x)
+{
+ return (((x)>>24)&0xF);
+}
+
+#define GET_APIC_ID(x) get_apic_id(x)
+
+#endif
--- /dev/null
+#ifndef __ASM_MACH_IPI_H
+#define __ASM_MACH_IPI_H
+
+void send_IPI_mask_bitmask(cpumask_t mask, int vector);
+void __send_IPI_shortcut(unsigned int shortcut, int vector);
+
+static inline void send_IPI_mask(cpumask_t mask, int vector)
+{
+ send_IPI_mask_bitmask(mask, vector);
+}
+
+static inline void send_IPI_allbutself(int vector)
+{
+ /*
+ * if there are no other CPUs in the system then we get an APIC send
+ * error if we try to broadcast, thus avoid sending IPIs in this case.
+ */
+ if (!(num_online_cpus() > 1))
+ return;
+
+ __send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
+ return;
+}
+
+static inline void send_IPI_all(int vector)
+{
+ __send_IPI_shortcut(APIC_DEST_ALLINC, vector);
+}
+
+#endif /* __ASM_MACH_IPI_H */
--- /dev/null
+#ifndef __ASM_MACH_MPPARSE_H
+#define __ASM_MACH_MPPARSE_H
+
+static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
+ struct mpc_config_translation *translation)
+{
+// Dprintk("Bus #%d is %s\n", m->mpc_busid, name);
+}
+
+static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
+ struct mpc_config_translation *translation)
+{
+}
+
+static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
+ char *productid)
+{
+ return 0;
+}
+
+/* Hook from generic ACPI tables.c */
+static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+ return 0;
+}
+
+
+#endif /* __ASM_MACH_MPPARSE_H */
--- /dev/null
+#ifndef __ASM_MACH_MPSPEC_H
+#define __ASM_MACH_MPSPEC_H
+
+#define MAX_IRQ_SOURCES 256
+
+#define MAX_MP_BUSSES 32
+
+#endif /* __ASM_MACH_MPSPEC_H */
--- /dev/null
+/*
+ * arch/i386/mach-generic/mach_reboot.h
+ *
+ * Machine specific reboot functions for generic.
+ * Split out from reboot.c by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef _MACH_REBOOT_H
+#define _MACH_REBOOT_H
+
+static inline void kb_wait(void)
+{
+ int i;
+
+ for (i = 0; i < 0x10000; i++)
+ if ((inb_p(0x64) & 0x02) == 0)
+ break;
+}
+
+static inline void mach_reboot(void)
+{
+ int i;
+ for (i = 0; i < 100; i++) {
+ kb_wait();
+ udelay(50);
+ outb(0xfe, 0x64); /* pulse reset low */
+ udelay(50);
+ }
+}
+
+#endif /* !_MACH_REBOOT_H */
--- /dev/null
+/*
+ * include/asm-i386/mach-default/mach_time.h
+ *
+ * Machine specific set RTC function for generic.
+ * Split out from time.c by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef _MACH_TIME_H
+#define _MACH_TIME_H
+
+#include <linux/mc146818rtc.h>
+
+/* for check timing call set_rtc_mmss() 500ms */
+/* used in arch/i386/time.c::do_timer_interrupt() */
+#define USEC_AFTER 500000
+#define USEC_BEFORE 500000
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ * sets the minutes. Usually you'll only notice that after reboot!
+ */
+static inline int mach_set_rtc_mmss(unsigned long nowtime)
+{
+ int retval = 0;
+ int real_seconds, real_minutes, cmos_minutes;
+ unsigned char save_control, save_freq_select;
+
+ save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+ CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+ cmos_minutes = CMOS_READ(RTC_MINUTES);
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ BCD_TO_BIN(cmos_minutes);
+
+ /*
+ * since we're only adjusting minutes and seconds,
+ * don't interfere with hour overflow. This avoids
+ * messing with unknown time zones but requires your
+ * RTC not to be off by more than 15 minutes
+ */
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BIN_TO_BCD(real_seconds);
+ BIN_TO_BCD(real_minutes);
+ }
+ CMOS_WRITE(real_seconds,RTC_SECONDS);
+ CMOS_WRITE(real_minutes,RTC_MINUTES);
+ } else {
+ printk(KERN_WARNING
+ "set_rtc_mmss: can't update from %d to %d\n",
+ cmos_minutes, real_minutes);
+ retval = -1;
+ }
+
+ /* The following flags have to be released exactly in this order,
+ * otherwise the DS12887 (popular MC146818A clone with integrated
+ * battery and quartz) will not reset the oscillator and will not
+ * update precisely 500 ms later. You won't find this mentioned in
+ * the Dallas Semiconductor data sheets, but who believes data
+ * sheets anyway ... -- Markus Kuhn
+ */
+ CMOS_WRITE(save_control, RTC_CONTROL);
+ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+ return retval;
+}
+
+static inline unsigned long mach_get_cmos_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec;
+ int i;
+
+ /* The Linux interpretation of the CMOS clock register contents:
+ * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+ * RTC registers show the second which has precisely just started.
+ * Let's hope other operating systems interpret the RTC the same way.
+ */
+ /* read RTC exactly on falling edge of update flag */
+ for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
+ if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+ break;
+ for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
+ if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+ break;
+ do { /* Isn't this overkill ? UIP above should guarantee consistency */
+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
+ } while (sec != CMOS_READ(RTC_SECONDS));
+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
+ if ((year += 1900) < 1970)
+ year += 100;
+
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+#endif /* !_MACH_TIME_H */
--- /dev/null
+/*
+ * include/asm-i386/mach-default/mach_timer.h
+ *
+ * Machine specific calibrate_tsc() for generic.
+ * Split out from timer_tsc.c by Osamu Tomita <tomita@cinet.co.jp>
+ */
+/* ------ Calibrate the TSC -------
+ * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
+ * Too much 64-bit arithmetic here to do this cleanly in C, and for
+ * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
+ * output busy loop as low as possible. We avoid reading the CTC registers
+ * directly because of the awkward 8-bit access mechanism of the 82C54
+ * device.
+ */
+#ifndef _MACH_TIMER_H
+#define _MACH_TIMER_H
+
+#define CALIBRATE_LATCH (5 * LATCH)
+
+static inline void mach_prepare_counter(void)
+{
+ /* Set the Gate high, disable speaker */
+ outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+
+ /*
+ * Now let's take care of CTC channel 2
+ *
+ * Set the Gate high, program CTC channel 2 for mode 0,
+ * (interrupt on terminal count mode), binary count,
+ * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+ *
+ * Some devices need a delay here.
+ */
+ outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
+ outb_p(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
+ outb_p(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
+}
+
+static inline void mach_countup(unsigned long *count_p)
+{
+ unsigned long count = 0;
+ do {
+ count++;
+ } while ((inb_p(0x61) & 0x20) == 0);
+ *count_p = count;
+}
+
+#endif /* !_MACH_TIMER_H */
--- /dev/null
+/*
+ * include/asm-i386/mach-default/mach_traps.h
+ *
+ * Machine specific NMI handling for generic.
+ * Split out from traps.c by Osamu Tomita <tomita@cinet.co.jp>
+ */
+#ifndef _MACH_TRAPS_H
+#define _MACH_TRAPS_H
+
+static inline void clear_mem_error(unsigned char reason)
+{
+ reason = (reason & 0xf) | 4;
+ outb(reason, 0x61);
+}
+
+static inline unsigned char get_nmi_reason(void)
+{
+ return inb(0x61);
+}
+
+static inline void reassert_nmi(void)
+{
+ outb(0x8f, 0x70);
+ inb(0x71); /* dummy */
+ outb(0x0f, 0x70);
+ inb(0x71); /* dummy */
+}
+
+#endif /* !_MACH_TRAPS_H */
--- /dev/null
+#ifndef __ASM_MACH_WAKECPU_H
+#define __ASM_MACH_WAKECPU_H
+
+/*
+ * This file copes with machines that wakeup secondary CPUs by the
+ * INIT, INIT, STARTUP sequence.
+ */
+
+#define WAKE_SECONDARY_VIA_INIT
+
+#define TRAMPOLINE_LOW phys_to_virt(0x467)
+#define TRAMPOLINE_HIGH phys_to_virt(0x469)
+
+#define boot_cpu_apicid boot_cpu_physical_apicid
+
+static inline void wait_for_init_deassert(atomic_t *deassert)
+{
+ while (!atomic_read(deassert));
+ return;
+}
+
+/* Nothing to do for most platforms, since cleared by the INIT cycle */
+static inline void smp_callin_clear_local_apic(void)
+{
+}
+
+static inline void store_NMI_vector(unsigned short *high, unsigned short *low)
+{
+}
+
+static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
+{
+}
+
+#if APIC_DEBUG
+ #define inquire_remote_apic(apicid) __inquire_remote_apic(apicid)
+#else
+ #define inquire_remote_apic(apicid) {}
+#endif
+
+#endif /* __ASM_MACH_WAKECPU_H */
--- /dev/null
+/*
+ * PCI BIOS function numbering for conventional PCI BIOS
+ * systems
+ */
+
+#define PCIBIOS_PCI_FUNCTION_ID 0xb1XX
+#define PCIBIOS_PCI_BIOS_PRESENT 0xb101
+#define PCIBIOS_FIND_PCI_DEVICE 0xb102
+#define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103
+#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106
+#define PCIBIOS_READ_CONFIG_BYTE 0xb108
+#define PCIBIOS_READ_CONFIG_WORD 0xb109
+#define PCIBIOS_READ_CONFIG_DWORD 0xb10a
+#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b
+#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c
+#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d
+#define PCIBIOS_GET_ROUTING_OPTIONS 0xb10e
+#define PCIBIOS_SET_PCI_HW_INT 0xb10f
+
--- /dev/null
+/**
+ * machine_specific_memory_setup - Hook for machine specific memory setup.
+ *
+ * Description:
+ * This is included late in kernel/setup.c so that it can make
+ * use of all of the static functions.
+ **/
+
+static char * __init machine_specific_memory_setup(void)
+{
+ char *who;
+
+
+ who = "BIOS-e820";
+
+ /*
+ * Try to copy the BIOS-supplied E820-map.
+ *
+ * Otherwise fake a memory map; one section from 0k->640k,
+ * the next section from 1mb->appropriate_mem_k
+ */
+ sanitize_e820_map(E820_MAP, &E820_MAP_NR);
+ if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
+ unsigned long mem_size;
+
+ /* compare results from other methods and take the greater */
+ if (ALT_MEM_K < EXT_MEM_K) {
+ mem_size = EXT_MEM_K;
+ who = "BIOS-88";
+ } else {
+ mem_size = ALT_MEM_K;
+ who = "BIOS-e801";
+ }
+
+ e820.nr_map = 0;
+ add_memory_region(0, LOWMEMSIZE(), E820_RAM);
+ add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
+ }
+ return who;
+}
--- /dev/null
+/* Hook to call BIOS initialisation function */
+
+/* no action for generic */
+
+#define ARCH_SETUP
--- /dev/null
+/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
+ * which needs to alter them. */
+
+static inline void smpboot_clear_io_apic_irqs(void)
+{
+ io_apic_irqs = 0;
+}
+
+static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
+{
+ CMOS_WRITE(0xa, 0xf);
+ local_flush_tlb();
+ Dprintk("1.\n");
+ *((volatile unsigned short *) TRAMPOLINE_HIGH) = start_eip >> 4;
+ Dprintk("2.\n");
+ *((volatile unsigned short *) TRAMPOLINE_LOW) = start_eip & 0xf;
+ Dprintk("3.\n");
+}
+
+static inline void smpboot_restore_warm_reset_vector(void)
+{
+ /*
+ * Install writable page 0 entry to set BIOS data area.
+ */
+ local_flush_tlb();
+
+ /*
+ * Paranoid: Set warm reset code and vector here back
+ * to default values.
+ */
+ CMOS_WRITE(0, 0xf);
+
+ *((volatile long *) phys_to_virt(0x467)) = 0;
+}
+
+static inline void smpboot_setup_io_apic(void)
+{
+ /*
+ * Here we can be sure that there is an IO-APIC in the system. Let's
+ * go and set it up:
+ */
+ if (!skip_ioapic_setup && nr_ioapics)
+ setup_IO_APIC();
+}
+++ /dev/null
-/*
- * based on linux-2.6.10/include/asm-i386/mach-default/mach_apic.h
- *
- */
-#ifndef __ASM_MACH_APIC_H
-#define __ASM_MACH_APIC_H
-
-#define APIC_DFR_VALUE (APIC_DFR_FLAT)
-#define esr_disable (0)
-
-/*
- * Set up the logical destination ID.
- *
- * Intel recommends to set DFR, LDR and TPR before enabling
- * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
- * document number 292116). So here it goes...
- */
-static inline void init_apic_ldr(void)
-{
- unsigned long val;
-
- apic_write_around(APIC_DFR, APIC_DFR_VALUE);
- val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
- val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
- apic_write_around(APIC_LDR, val);
-}
-
-static inline int apic_id_registered(void)
-{
- return test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map);
-}
-#endif /* __ASM_MACH_APIC_H */
#ifndef __ASM_MPSPEC_H
#define __ASM_MPSPEC_H
-#include <xen/config.h>
-#include <xen/types.h>
+#include <xen/cpumask.h>
+#include <asm/mpspec_def.h>
+#include <mach_mpspec.h>
-/*
- * Structure definitions for SMP machines following the
- * Intel Multiprocessing Specification 1.1 and 1.4.
- */
-
-/*
- * This tag identifies where the SMP configuration
- * information is.
- */
-
-#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_')
-
-/*
- * a maximum of 16 APICs with the current APIC ID architecture.
- * xAPICs can have up to 256. SAPICs have 16 ID bits.
- */
-#ifdef CONFIG_X86_CLUSTERED_APIC
-#define MAX_APICS 256
-#else
-#define MAX_APICS 16
-#endif
-
-#define MAX_MPC_ENTRY 1024
-
-struct intel_mp_floating
-{
- char mpf_signature[4]; /* "_MP_" */
- unsigned int mpf_physptr; /* Configuration table address */
- unsigned char mpf_length; /* Our length (paragraphs) */
- unsigned char mpf_specification;/* Specification version */
- unsigned char mpf_checksum; /* Checksum (makes sum 0) */
- unsigned char mpf_feature1; /* Standard or configuration ? */
- unsigned char mpf_feature2; /* Bit7 set for IMCR|PIC */
- unsigned char mpf_feature3; /* Unused (0) */
- unsigned char mpf_feature4; /* Unused (0) */
- unsigned char mpf_feature5; /* Unused (0) */
-};
-
-struct mp_config_table
-{
- char mpc_signature[4];
-#define MPC_SIGNATURE "PCMP"
- unsigned short mpc_length; /* Size of table */
- char mpc_spec; /* 0x01 */
- char mpc_checksum;
- char mpc_oem[8];
- char mpc_productid[12];
- unsigned int mpc_oemptr; /* 0 if not present */
- unsigned short mpc_oemsize; /* 0 if not present */
- unsigned short mpc_oemcount;
- unsigned int mpc_lapic; /* APIC address */
- unsigned int reserved;
-};
-
-/* Followed by entries */
-
-#define MP_PROCESSOR 0
-#define MP_BUS 1
-#define MP_IOAPIC 2
-#define MP_INTSRC 3
-#define MP_LINTSRC 4
-#define MP_TRANSLATION 192 /* Used by IBM NUMA-Q to describe node locality */
-
-struct mpc_config_processor
-{
- unsigned char mpc_type;
- unsigned char mpc_apicid; /* Local APIC number */
- unsigned char mpc_apicver; /* Its versions */
- unsigned char mpc_cpuflag;
-#define CPU_ENABLED 1 /* Processor is available */
-#define CPU_BOOTPROCESSOR 2 /* Processor is the BP */
- unsigned int mpc_cpufeature;
-#define CPU_STEPPING_MASK 0x0F
-#define CPU_MODEL_MASK 0xF0
-#define CPU_FAMILY_MASK 0xF00
- unsigned int mpc_featureflag; /* CPUID feature value */
- unsigned int mpc_reserved[2];
-};
-
-struct mpc_config_bus
-{
- unsigned char mpc_type;
- unsigned char mpc_busid;
- unsigned char mpc_bustype[6] __attribute((packed));
-};
-
-/* List of Bus Type string values, Intel MP Spec. */
-#define BUSTYPE_EISA "EISA"
-#define BUSTYPE_ISA "ISA"
-#define BUSTYPE_INTERN "INTERN" /* Internal BUS */
-#define BUSTYPE_MCA "MCA"
-#define BUSTYPE_VL "VL" /* Local bus */
-#define BUSTYPE_PCI "PCI"
-#define BUSTYPE_PCMCIA "PCMCIA"
-#define BUSTYPE_CBUS "CBUS"
-#define BUSTYPE_CBUSII "CBUSII"
-#define BUSTYPE_FUTURE "FUTURE"
-#define BUSTYPE_MBI "MBI"
-#define BUSTYPE_MBII "MBII"
-#define BUSTYPE_MPI "MPI"
-#define BUSTYPE_MPSA "MPSA"
-#define BUSTYPE_NUBUS "NUBUS"
-#define BUSTYPE_TC "TC"
-#define BUSTYPE_VME "VME"
-#define BUSTYPE_XPRESS "XPRESS"
-
-struct mpc_config_ioapic
-{
- unsigned char mpc_type;
- unsigned char mpc_apicid;
- unsigned char mpc_apicver;
- unsigned char mpc_flags;
-#define MPC_APIC_USABLE 0x01
- unsigned int mpc_apicaddr;
-};
-
-struct mpc_config_intsrc
-{
- unsigned char mpc_type;
- unsigned char mpc_irqtype;
- unsigned short mpc_irqflag;
- unsigned char mpc_srcbus;
- unsigned char mpc_srcbusirq;
- unsigned char mpc_dstapic;
- unsigned char mpc_dstirq;
-};
-
-enum mp_irq_source_types {
- mp_INT = 0,
- mp_NMI = 1,
- mp_SMI = 2,
- mp_ExtINT = 3
-};
-
-#define MP_IRQDIR_DEFAULT 0
-#define MP_IRQDIR_HIGH 1
-#define MP_IRQDIR_LOW 3
-
-
-struct mpc_config_lintsrc
-{
- unsigned char mpc_type;
- unsigned char mpc_irqtype;
- unsigned short mpc_irqflag;
- unsigned char mpc_srcbusid;
- unsigned char mpc_srcbusirq;
- unsigned char mpc_destapic;
-#define MP_APIC_ALL 0xFF
- unsigned char mpc_destapiclint;
-};
-
-struct mp_config_oemtable
-{
- char oem_signature[4];
-#define MPC_OEM_SIGNATURE "_OEM"
- unsigned short oem_length; /* Size of table */
- char oem_rev; /* 0x01 */
- char oem_checksum;
- char mpc_oem[8];
-};
-
-struct mpc_config_translation
-{
- unsigned char mpc_type;
- unsigned char trans_len;
- unsigned char trans_type;
- unsigned char trans_quad;
- unsigned char trans_global;
- unsigned char trans_local;
- unsigned short trans_reserved;
-};
-
-/*
- * Default configurations
- *
- * 1 2 CPU ISA 82489DX
- * 2 2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining
- * 3 2 CPU EISA 82489DX
- * 4 2 CPU MCA 82489DX
- * 5 2 CPU ISA+PCI
- * 6 2 CPU EISA+PCI
- * 7 2 CPU MCA+PCI
- */
-
-#ifdef CONFIG_MULTIQUAD
-#define MAX_IRQ_SOURCES 512
-#else /* !CONFIG_MULTIQUAD */
-#define MAX_IRQ_SOURCES 256
-#endif /* CONFIG_MULTIQUAD */
-
-#define MAX_MP_BUSSES 32
-enum mp_bustype {
- MP_BUS_ISA = 1,
- MP_BUS_EISA,
- MP_BUS_PCI,
- MP_BUS_MCA
-};
-extern int *mp_bus_id_to_type;
-extern int *mp_bus_id_to_node;
-extern int *mp_bus_id_to_local;
-extern int *mp_bus_id_to_pci_bus;
+extern int mp_bus_id_to_type [MAX_MP_BUSSES];
+extern int mp_bus_id_to_node [MAX_MP_BUSSES];
+extern int mp_bus_id_to_local [MAX_MP_BUSSES];
extern int quad_local_to_mp_bus_id [NR_CPUS/4][4];
+extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
extern unsigned int boot_cpu_physical_apicid;
-/*extern unsigned long phys_cpu_present_map;*/
extern int smp_found_config;
extern void find_smp_config (void);
extern void get_smp_config (void);
-/*extern int nr_ioapics;*/
+extern int nr_ioapics;
extern int apic_version [MAX_APICS];
-/*extern int mp_irq_entries;*/
-/*extern struct mpc_config_intsrc *mp_irqs;*/
-/*extern int mpc_default_type;*/
+extern int mp_bus_id_to_type [MAX_MP_BUSSES];
+extern int mp_irq_entries;
+extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
+extern int mpc_default_type;
+extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
extern int mp_current_pci_id;
extern unsigned long mp_lapic_addr;
-/*extern int pic_mode;*/
+extern int pic_mode;
extern int using_apic_timer;
#ifdef CONFIG_ACPI_BOOT
extern void mp_register_lapic (u8 id, u8 enabled);
extern void mp_register_lapic_address (u64 address);
-
-#ifdef CONFIG_X86_IO_APIC
-extern void mp_register_ioapic (u8 id, u32 address, u32 irq_base);
-extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq);
+extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
+extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi);
extern void mp_config_acpi_legacy_irqs (void);
-extern void mp_config_ioapic_for_sci(int irq);
-extern void mp_parse_prt (void);
-#else /*!CONFIG_X86_IO_APIC*/
-static inline void mp_config_ioapic_for_sci(int irq) { }
-#endif /*!CONFIG_X86_IO_APIC*/
-
+extern int mp_register_gsi (u32 gsi, int edge_level, int active_high_low);
#endif /*CONFIG_ACPI_BOOT*/
+#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
+
+struct physid_mask
+{
+ unsigned long mask[PHYSID_ARRAY_SIZE];
+};
+
+typedef struct physid_mask physid_mask_t;
+
+#define physid_set(physid, map) set_bit(physid, (map).mask)
+#define physid_clear(physid, map) clear_bit(physid, (map).mask)
+#define physid_isset(physid, map) test_bit(physid, (map).mask)
+#define physid_test_and_set(physid, map) test_and_set_bit(physid, (map).mask)
+
+#define physids_and(dst, src1, src2) bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+#define physids_or(dst, src1, src2) bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+#define physids_clear(map) bitmap_zero((map).mask, MAX_APICS)
+#define physids_complement(dst, src) bitmap_complement((dst).mask,(src).mask, MAX_APICS)
+#define physids_empty(map) bitmap_empty((map).mask, MAX_APICS)
+#define physids_equal(map1, map2) bitmap_equal((map1).mask, (map2).mask, MAX_APICS)
+#define physids_weight(map) bitmap_weight((map).mask, MAX_APICS)
+#define physids_shift_right(d, s, n) bitmap_shift_right((d).mask, (s).mask, n, MAX_APICS)
+#define physids_shift_left(d, s, n) bitmap_shift_left((d).mask, (s).mask, n, MAX_APICS)
+#define physids_coerce(map) ((map).mask[0])
+
+#define physids_promote(physids) \
+ ({ \
+ physid_mask_t __physid_mask = PHYSID_MASK_NONE; \
+ __physid_mask.mask[0] = physids; \
+ __physid_mask; \
+ })
+
+#define physid_mask_of_physid(physid) \
+ ({ \
+ physid_mask_t __physid_mask = PHYSID_MASK_NONE; \
+ physid_set(physid, __physid_mask); \
+ __physid_mask; \
+ })
+
+#define PHYSID_MASK_ALL { {[0 ... PHYSID_ARRAY_SIZE-1] = ~0UL} }
+#define PHYSID_MASK_NONE { {[0 ... PHYSID_ARRAY_SIZE-1] = 0UL} }
+
+extern physid_mask_t phys_cpu_present_map;
+
#endif
--- /dev/null
+#ifndef __ASM_MPSPEC_DEF_H
+#define __ASM_MPSPEC_DEF_H
+
+/*
+ * Structure definitions for SMP machines following the
+ * Intel Multiprocessing Specification 1.1 and 1.4.
+ */
+
+/*
+ * This tag identifies where the SMP configuration
+ * information is.
+ */
+
+#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_')
+
+#define MAX_MPC_ENTRY 1024
+#define MAX_APICS 256
+
+struct intel_mp_floating
+{
+ char mpf_signature[4]; /* "_MP_" */
+ unsigned int mpf_physptr; /* Configuration table address */
+ unsigned char mpf_length; /* Our length (paragraphs) */
+ unsigned char mpf_specification;/* Specification version */
+ unsigned char mpf_checksum; /* Checksum (makes sum 0) */
+ unsigned char mpf_feature1; /* Standard or configuration ? */
+ unsigned char mpf_feature2; /* Bit7 set for IMCR|PIC */
+ unsigned char mpf_feature3; /* Unused (0) */
+ unsigned char mpf_feature4; /* Unused (0) */
+ unsigned char mpf_feature5; /* Unused (0) */
+};
+
+struct mp_config_table
+{
+ char mpc_signature[4];
+#define MPC_SIGNATURE "PCMP"
+ unsigned short mpc_length; /* Size of table */
+ char mpc_spec; /* 0x01 */
+ char mpc_checksum;
+ char mpc_oem[8];
+ char mpc_productid[12];
+ unsigned int mpc_oemptr; /* 0 if not present */
+ unsigned short mpc_oemsize; /* 0 if not present */
+ unsigned short mpc_oemcount;
+ unsigned int mpc_lapic; /* APIC address */
+ unsigned int reserved;
+};
+
+/* Followed by entries */
+
+#define MP_PROCESSOR 0
+#define MP_BUS 1
+#define MP_IOAPIC 2
+#define MP_INTSRC 3
+#define MP_LINTSRC 4
+#define MP_TRANSLATION 192 /* Used by IBM NUMA-Q to describe node locality */
+
+struct mpc_config_processor
+{
+ unsigned char mpc_type;
+ unsigned char mpc_apicid; /* Local APIC number */
+ unsigned char mpc_apicver; /* Its versions */
+ unsigned char mpc_cpuflag;
+#define CPU_ENABLED 1 /* Processor is available */
+#define CPU_BOOTPROCESSOR 2 /* Processor is the BP */
+ unsigned int mpc_cpufeature;
+#define CPU_STEPPING_MASK 0x0F
+#define CPU_MODEL_MASK 0xF0
+#define CPU_FAMILY_MASK 0xF00
+ unsigned int mpc_featureflag; /* CPUID feature value */
+ unsigned int mpc_reserved[2];
+};
+
+struct mpc_config_bus
+{
+ unsigned char mpc_type;
+ unsigned char mpc_busid;
+ unsigned char mpc_bustype[6] __attribute((packed));
+};
+
+/* List of Bus Type string values, Intel MP Spec. */
+#define BUSTYPE_EISA "EISA"
+#define BUSTYPE_ISA "ISA"
+#define BUSTYPE_INTERN "INTERN" /* Internal BUS */
+#define BUSTYPE_MCA "MCA"
+#define BUSTYPE_VL "VL" /* Local bus */
+#define BUSTYPE_PCI "PCI"
+#define BUSTYPE_PCMCIA "PCMCIA"
+#define BUSTYPE_CBUS "CBUS"
+#define BUSTYPE_CBUSII "CBUSII"
+#define BUSTYPE_FUTURE "FUTURE"
+#define BUSTYPE_MBI "MBI"
+#define BUSTYPE_MBII "MBII"
+#define BUSTYPE_MPI "MPI"
+#define BUSTYPE_MPSA "MPSA"
+#define BUSTYPE_NUBUS "NUBUS"
+#define BUSTYPE_TC "TC"
+#define BUSTYPE_VME "VME"
+#define BUSTYPE_XPRESS "XPRESS"
+#define BUSTYPE_NEC98 "NEC98"
+
+struct mpc_config_ioapic
+{
+ unsigned char mpc_type;
+ unsigned char mpc_apicid;
+ unsigned char mpc_apicver;
+ unsigned char mpc_flags;
+#define MPC_APIC_USABLE 0x01
+ unsigned int mpc_apicaddr;
+};
+
+struct mpc_config_intsrc
+{
+ unsigned char mpc_type;
+ unsigned char mpc_irqtype;
+ unsigned short mpc_irqflag;
+ unsigned char mpc_srcbus;
+ unsigned char mpc_srcbusirq;
+ unsigned char mpc_dstapic;
+ unsigned char mpc_dstirq;
+};
+
+enum mp_irq_source_types {
+ mp_INT = 0,
+ mp_NMI = 1,
+ mp_SMI = 2,
+ mp_ExtINT = 3
+};
+
+#define MP_IRQDIR_DEFAULT 0
+#define MP_IRQDIR_HIGH 1
+#define MP_IRQDIR_LOW 3
+
+
+struct mpc_config_lintsrc
+{
+ unsigned char mpc_type;
+ unsigned char mpc_irqtype;
+ unsigned short mpc_irqflag;
+ unsigned char mpc_srcbusid;
+ unsigned char mpc_srcbusirq;
+ unsigned char mpc_destapic;
+#define MP_APIC_ALL 0xFF
+ unsigned char mpc_destapiclint;
+};
+
+struct mp_config_oemtable
+{
+ char oem_signature[4];
+#define MPC_OEM_SIGNATURE "_OEM"
+ unsigned short oem_length; /* Size of table */
+ char oem_rev; /* 0x01 */
+ char oem_checksum;
+ char mpc_oem[8];
+};
+
+struct mpc_config_translation
+{
+ unsigned char mpc_type;
+ unsigned char trans_len;
+ unsigned char trans_type;
+ unsigned char trans_quad;
+ unsigned char trans_global;
+ unsigned char trans_local;
+ unsigned short trans_reserved;
+};
+
+/*
+ * Default configurations
+ *
+ * 1 2 CPU ISA 82489DX
+ * 2 2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining
+ * 3 2 CPU EISA 82489DX
+ * 4 2 CPU MCA 82489DX
+ * 5 2 CPU ISA+PCI
+ * 6 2 CPU EISA+PCI
+ * 7 2 CPU MCA+PCI
+ */
+
+enum mp_bustype {
+ MP_BUS_ISA = 1,
+ MP_BUS_EISA,
+ MP_BUS_PCI,
+ MP_BUS_MCA,
+ MP_BUS_NEC98
+};
+#endif
+
return order;
}
-extern void zap_low_mappings(void);
-
/* Map physical byte range (@p, @p+@s) at virt address @v in pagetable @pt. */
extern int
map_pages(
#define __ASM_X86_PROCESSOR_H
#ifndef __ASSEMBLY__
-#include <asm/page.h>
-#include <asm/types.h>
-#include <asm/cpufeature.h>
-#include <asm/desc.h>
-#include <asm/flushtlb.h>
#include <xen/config.h>
-#include <xen/spinlock.h>
#include <xen/cache.h>
-#include <asm/vmx_vmcs.h>
+#include <xen/types.h>
#include <public/xen.h>
+#include <asm/types.h>
+#include <asm/cpufeature.h>
+#include <asm/desc.h>
#endif
/*
int x86_cache_size; /* in KB - for CPUS that support this call */
int x86_clflush_size;
int x86_tlbsize; /* number of 4K pages in DTLB/ITLB combined */
-} __attribute__((__aligned__(SMP_CACHE_BYTES)));
+} __cacheline_aligned;
/*
* capabilities of CPUs
u16 bitmap;
/* Pads the TSS to be cacheline-aligned (total size is 0x80). */
u8 __cacheline_filler[24];
-} __cacheline_aligned PACKED;
+} __cacheline_aligned __attribute__((packed));
#define IDT_ENTRIES 256
extern idt_entry_t idt_table[];
#ifndef __ASM_SMP_H
#define __ASM_SMP_H
+/*
+ * We need the APIC definitions automatically as part of 'smp.h'
+ */
#ifndef __ASSEMBLY__
#include <xen/config.h>
+#include <xen/kernel.h>
+#include <xen/cpumask.h>
+#endif
+
+#ifdef CONFIG_X86_LOCAL_APIC
+#ifndef __ASSEMBLY__
#include <asm/fixmap.h>
+#include <asm/bitops.h>
#include <asm/mpspec.h>
+#ifdef CONFIG_X86_IO_APIC
#include <asm/io_apic.h>
+#endif
#include <asm/apic.h>
#endif
+#endif
+#define BAD_APICID 0xFFu
#ifdef CONFIG_SMP
#ifndef __ASSEMBLY__
*/
extern void smp_alloc_memory(void);
-extern unsigned long phys_cpu_present_map;
-extern unsigned long cpu_online_map;
-extern volatile unsigned long smp_invalidate_needed;
extern int pic_mode;
extern int smp_num_siblings;
-extern int cpu_sibling_map[];
+extern cpumask_t cpu_sibling_map[];
-/*
- * On x86 all CPUs are mapped 1:1 to the APIC space.
- * This simplifies scheduling and IPI sending and
- * compresses data structures.
- */
-static inline int cpu_logical_map(int cpu)
-{
- return cpu;
-}
-static inline int cpu_number_map(int cpu)
-{
- return cpu;
-}
+extern void smp_flush_tlb(void);
+extern void smp_invalidate_rcv(void); /* Process an NMI */
+extern void (*mtrr_hook) (void);
+extern void zap_low_mappings (void);
-/*
- * Some lowlevel functions might want to know about
- * the real APIC ID <-> CPU # mapping.
- */
#define MAX_APICID 256
-extern volatile int cpu_to_physical_apicid[NR_CPUS];
-extern volatile int physical_apicid_to_cpu[MAX_APICID];
-extern volatile int cpu_to_logical_apicid[NR_CPUS];
-extern volatile int logical_apicid_to_cpu[MAX_APICID];
-
-/*
- * General functions that each host system must provide.
- */
-
-/*extern void smp_boot_cpus(void);*/
-extern void smp_store_cpu_info(int id); /* Store per CPU info (like the initial udelay numbers */
+extern u8 x86_cpu_to_apicid[];
/*
* This function is needed by all SMP systems. It must _always_ be valid
* from the initial startup. We map APIC_BASE very early in page_setup(),
* so this is correct in the x86 case.
*/
+#define __smp_processor_id() (current->processor)
-#define smp_processor_id() (current->processor)
+extern cpumask_t cpu_callout_map;
+extern cpumask_t cpu_callin_map;
+#define cpu_possible_map cpu_callout_map
-static __inline int hard_smp_processor_id(void)
+/* We don't mark CPUs online until __cpu_up(), so we need another measure */
+static inline int num_booting_cpus(void)
+{
+ return cpus_weight(cpu_callout_map);
+}
+
+extern void map_cpu_to_logical_apicid(void);
+extern void unmap_cpu_to_logical_apicid(int cpu);
+
+#ifdef CONFIG_X86_LOCAL_APIC
+
+#ifdef APIC_DEFINITION
+extern int hard_smp_processor_id(void);
+#else
+#include <mach_apicdef.h>
+static inline int hard_smp_processor_id(void)
{
/* we don't want to mark this access volatile - bad code generation */
- return GET_APIC_ID(*(unsigned *)(APIC_BASE+APIC_ID));
+ return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
}
+#endif
static __inline int logical_smp_processor_id(void)
{
/* we don't want to mark this access volatile - bad code generation */
- return GET_APIC_LOGICAL_ID(*(unsigned *)(APIC_BASE+APIC_LDR));
+ return GET_APIC_LOGICAL_ID(*(unsigned int *)(APIC_BASE+APIC_LDR));
}
+#endif
#endif /* !__ASSEMBLY__ */
#define NO_PROC_ID 0xFF /* No processor magic marker */
-/*
- * This magic constant controls our willingness to transfer
- * a process across CPUs. Such a transfer incurs misses on the L1
- * cache, and on a P6 or P5 with multiple L2 caches L2 hits. My
- * gut feeling is this will vary by board in value. For a board
- * with separate L2 cache it probably depends also on the RSS, and
- * for a board with shared L2 cache it ought to decay fast as other
- * processes are run.
- */
-
-#define PROC_CHANGE_PENALTY 15 /* Schedule penalty */
-
#endif
#endif
#ifndef __ASM_SMPBOOT_H
#define __ASM_SMPBOOT_H
-/*emum for clustered_apic_mode values*/
-enum{
- CLUSTERED_APIC_NONE = 0,
- CLUSTERED_APIC_XAPIC,
- CLUSTERED_APIC_NUMAQ
-};
-
-#ifdef CONFIG_X86_CLUSTERED_APIC
-extern unsigned int apic_broadcast_id;
-extern unsigned char clustered_apic_mode;
-extern unsigned char esr_disable;
-extern unsigned char int_delivery_mode;
-extern unsigned int int_dest_addr_mode;
-extern int cyclone_setup(char*);
-
-static inline void detect_clustered_apic(char* oem, char* prod)
-{
- /*
- * Can't recognize Summit xAPICs at present, so use the OEM ID.
- */
- if (!strncmp(oem, "IBM ENSW", 8) && !strncmp(prod, "VIGIL SMP", 9)){
- clustered_apic_mode = CLUSTERED_APIC_XAPIC;
- apic_broadcast_id = APIC_BROADCAST_ID_XAPIC;
- int_dest_addr_mode = APIC_DEST_PHYSICAL;
- int_delivery_mode = dest_Fixed;
- esr_disable = 1;
- /*Start cyclone clock*/
- cyclone_setup(0);
- /* check for ACPI tables */
- } else if (!strncmp(oem, "IBM", 3) &&
- (!strncmp(prod, "SERVIGIL", 8) ||
- !strncmp(prod, "EXA", 3) ||
- !strncmp(prod, "RUTHLESS", 8))){
- clustered_apic_mode = CLUSTERED_APIC_XAPIC;
- apic_broadcast_id = APIC_BROADCAST_ID_XAPIC;
- int_dest_addr_mode = APIC_DEST_PHYSICAL;
- int_delivery_mode = dest_Fixed;
- esr_disable = 1;
- /*Start cyclone clock*/
- cyclone_setup(0);
- } else if (!strncmp(oem, "IBM NUMA", 8)){
- clustered_apic_mode = CLUSTERED_APIC_NUMAQ;
- apic_broadcast_id = APIC_BROADCAST_ID_APIC;
- int_dest_addr_mode = APIC_DEST_LOGICAL;
- int_delivery_mode = dest_LowestPrio;
- esr_disable = 1;
- }
-}
-#define INT_DEST_ADDR_MODE (int_dest_addr_mode)
-#define INT_DELIVERY_MODE (int_delivery_mode)
-#else /* CONFIG_X86_CLUSTERED_APIC */
-#define apic_broadcast_id (APIC_BROADCAST_ID_APIC)
-#define clustered_apic_mode (CLUSTERED_APIC_NONE)
-#define esr_disable (0)
-#define detect_clustered_apic(x,y)
-#define INT_DEST_ADDR_MODE (APIC_DEST_LOGICAL) /* logical delivery */
-#define INT_DELIVERY_MODE (dest_LowestPrio)
-#endif /* CONFIG_X86_CLUSTERED_APIC */
-#define BAD_APICID 0xFFu
-
-#define TRAMPOLINE_LOW phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0x8:0x467)
-#define TRAMPOLINE_HIGH phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0xa:0x469)
-
-#define boot_cpu_apicid ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?boot_cpu_logical_apicid:boot_cpu_physical_apicid)
-
-extern unsigned char raw_phys_apicid[NR_CPUS];
-
-/*
- * How to map from the cpu_present_map
- */
-static inline int cpu_present_to_apicid(int mps_cpu)
-{
- if (clustered_apic_mode == CLUSTERED_APIC_XAPIC)
- return raw_phys_apicid[mps_cpu];
- if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ)
- return (mps_cpu/4)*16 + (1<<(mps_cpu%4));
- return mps_cpu;
-}
-
static inline unsigned long apicid_to_phys_cpu_present(int apicid)
{
- if(clustered_apic_mode)
- return 1UL << (((apicid >> 4) << 2) + (apicid & 0x3));
return 1UL << apicid;
}
-#define physical_to_logical_apicid(phys_apic) ( (1ul << (phys_apic & 0x3)) | (phys_apic & 0xF0u) )
-
-/*
- * Mappings between logical cpu number and logical / physical apicid
- * The first four macros are trivial, but it keeps the abstraction consistent
- */
extern volatile int logical_apicid_2_cpu[];
extern volatile int cpu_2_logical_apicid[];
extern volatile int physical_apicid_2_cpu[];
extern volatile int cpu_2_physical_apicid[];
-#define logical_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid]
-#define cpu_to_logical_apicid(cpu) cpu_2_logical_apicid[cpu]
-#define physical_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid]
-#define cpu_to_physical_apicid(cpu) cpu_2_physical_apicid[cpu]
-#ifdef CONFIG_MULTIQUAD /* use logical IDs to bootstrap */
-#define boot_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid]
-#define cpu_to_boot_apicid(cpu) cpu_2_logical_apicid[cpu]
-#else /* !CONFIG_MULTIQUAD */ /* use physical IDs to bootstrap */
#define boot_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid]
-#define cpu_to_boot_apicid(cpu) cpu_2_physical_apicid[cpu]
-#endif /* CONFIG_MULTIQUAD */
-#ifdef CONFIG_X86_CLUSTERED_APIC
-static inline int target_cpus(void)
-{
- static int cpu;
- switch(clustered_apic_mode){
- case CLUSTERED_APIC_NUMAQ:
- /* Broadcast intrs to local quad only. */
- return APIC_BROADCAST_ID_APIC;
- case CLUSTERED_APIC_XAPIC:
- /*round robin the interrupts*/
- cpu = (cpu+1)%smp_num_cpus;
- return cpu_to_physical_apicid(cpu);
- default:
- }
- return cpu_online_map;
-}
-#else
-#define target_cpus() (cpu_online_map)
-#endif
#endif
return old;
}
+#define __HAVE_ARCH_CMPXCHG
#define cmpxchg(ptr,o,n)\
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
(unsigned long)(n),sizeof(*(ptr))))
#ifndef __X86_TIME_H__
#define __X86_TIME_H__
-/* nothing */
+extern int timer_ack;
#endif /* __X86_TIME_H__ */
struct acpi_table_rsdt {
struct acpi_table_header header;
- u32 entry[1];
+ u32 entry[8];
} __attribute__ ((packed));
/* Extended System Description Table (XSDT) */
u8 page_protect;
} __attribute__ ((packed));
+/*
+ * Simple Boot Flags
+ * http://www.microsoft.com/whdc/hwdev/resources/specs/simp_bios.mspx
+ */
+struct acpi_table_sbf
+{
+ u8 sbf_signature[4];
+ u32 sbf_len;
+ u8 sbf_revision;
+ u8 sbf_csum;
+ u8 sbf_oemid[6];
+ u8 sbf_oemtable[8];
+ u8 sbf_revdata[4];
+ u8 sbf_creator[4];
+ u8 sbf_crearev[4];
+ u8 sbf_cmos;
+ u8 sbf_spare[3];
+} __attribute__ ((packed));
+
/*
* System Resource Affinity Table (SRAT)
- * see http://www.microsoft.com/hwdev/design/srat.htm
+ * http://www.microsoft.com/whdc/hwdev/platform/proc/SRAT.mspx
*/
struct acpi_table_srat {
/* Embedded Controller Boot Resources Table (ECDT) */
struct acpi_table_ecdt {
- struct acpi_table_header header;
+ struct acpi_table_header header;
struct acpi_generic_address ec_control;
struct acpi_generic_address ec_data;
u32 uid;
char ec_id[0];
} __attribute__ ((packed));
+/* PCI MMCONFIG */
+
+struct acpi_table_mcfg {
+ struct acpi_table_header header;
+ u8 reserved[8];
+ u32 base_address;
+ u32 base_reserved;
+} __attribute__ ((packed));
+
/* Table Handlers */
enum acpi_table_id {
ACPI_SSDT,
ACPI_SPMI,
ACPI_HPET,
+ ACPI_MCFG,
ACPI_TABLE_COUNT
};
extern acpi_table_handler acpi_table_ops[ACPI_TABLE_COUNT];
-typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header);
+typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header, const unsigned long end);
char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
unsigned long acpi_find_rsdp (void);
int acpi_boot_init (void);
+int acpi_boot_table_init (void);
int acpi_numa_init (void);
int acpi_table_init (void);
int acpi_table_parse (enum acpi_table_id id, acpi_table_handler handler);
int acpi_get_table_header_early (enum acpi_table_id id, struct acpi_table_header **header);
-int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler);
-int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler);
+int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries);
+int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries);
void acpi_table_print (struct acpi_table_header *header, unsigned long phys_addr);
void acpi_table_print_madt_entry (acpi_table_entry_header *madt);
void acpi_table_print_srat_entry (acpi_table_entry_header *srat);
void acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma);
void acpi_numa_arch_fixup(void);
-#else /*!CONFIG_ACPI_BOOT*/
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+/* Arch dependent functions for cpu hotplug support */
+int acpi_map_lsapic(acpi_handle handle, int *pcpu);
+int acpi_unmap_lsapic(int cpu);
+#endif /* CONFIG_ACPI_HOTPLUG_CPU */
+
+extern int acpi_mp_config;
+
+extern u32 pci_mmcfg_base_addr;
+
+extern int sbf_port ;
+
+#else /*!CONFIG_ACPI_BOOT*/
+
+#define acpi_mp_config 0
static inline int acpi_boot_init(void)
{
return 0;
}
-#endif /*!CONFIG_ACPI_BOOT*/
+static inline int acpi_boot_table_init(void)
+{
+ return 0;
+}
+
+#endif /*!CONFIG_ACPI_BOOT*/
+unsigned int acpi_register_gsi (u32 gsi, int edge_level, int active_high_low);
+int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
+
+/*
+ * This function undoes the effect of one call to acpi_register_gsi().
+ * If this matches the last registration, any IRQ resources for gsi
+ * are freed.
+ */
+#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
+void acpi_unregister_gsi (u32 gsi);
+#endif
#ifdef CONFIG_ACPI_PCI
struct pci_dev;
int acpi_pci_irq_enable (struct pci_dev *dev);
-int acpi_pci_irq_init (void);
+void acpi_penalize_isa_irq(int irq);
+
+#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
+void acpi_pci_irq_disable (struct pci_dev *dev);
+#endif
struct acpi_pci_driver {
struct acpi_pci_driver *next;
#ifdef CONFIG_ACPI_EC
-int ec_read(u8 addr, u8 *val);
-int ec_write(u8 addr, u8 val);
+extern int ec_read(u8 addr, u8 *val);
+extern int ec_write(u8 addr, u8 val);
#endif /*CONFIG_ACPI_EC*/
#ifdef CONFIG_ACPI_INTERPRETER
-int acpi_blacklisted(void);
+extern int acpi_blacklisted(void);
+extern void acpi_bios_year(char *s);
#else /*!CONFIG_ACPI_INTERPRETER*/
#endif /*!CONFIG_ACPI_INTERPRETER*/
+#define ACPI_CSTATE_LIMIT_DEFINED /* for driver builds */
+#ifdef CONFIG_ACPI
+
+/*
+ * Set highest legal C-state
+ * 0: C0 okay, but not C1
+ * 1: C1 okay, but not C2
+ * 2: C2 okay, but not C3 etc.
+ */
+
+extern unsigned int max_cstate;
+
+static inline unsigned int acpi_get_cstate_limit(void)
+{
+ return max_cstate;
+}
+static inline void acpi_set_cstate_limit(unsigned int new_limit)
+{
+ max_cstate = new_limit;
+ return;
+}
+#else
+static inline unsigned int acpi_get_cstate_limit(void) { return 0; }
+static inline void acpi_set_cstate_limit(unsigned int new_limit) { return; }
+#endif
+
+#ifdef CONFIG_ACPI_NUMA
+int acpi_get_pxm(acpi_handle handle);
+#else
+static inline int acpi_get_pxm(acpi_handle handle)
+{
+ return 0;
+}
+#endif
+
+extern int pnpacpi_disabled;
+
#endif /*_LINUX_ACPI_H*/
--- /dev/null
+#ifndef __XEN_BITMAP_H
+#define __XEN_BITMAP_H
+
+#ifndef __ASSEMBLY__
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/types.h>
+
+/*
+ * bitmaps provide bit arrays that consume one or more unsigned
+ * longs. The bitmap interface and available operations are listed
+ * here, in bitmap.h
+ *
+ * Function implementations generic to all architectures are in
+ * lib/bitmap.c. Functions implementations that are architecture
+ * specific are in various include/asm-<arch>/bitops.h headers
+ * and other arch/<arch> specific files.
+ *
+ * See lib/bitmap.c for more details.
+ */
+
+/*
+ * The available bitmap operations and their rough meaning in the
+ * case that the bitmap is a single unsigned long are thus:
+ *
+ * bitmap_zero(dst, nbits) *dst = 0UL
+ * bitmap_fill(dst, nbits) *dst = ~0UL
+ * bitmap_copy(dst, src, nbits) *dst = *src
+ * bitmap_and(dst, src1, src2, nbits) *dst = *src1 & *src2
+ * bitmap_or(dst, src1, src2, nbits) *dst = *src1 | *src2
+ * bitmap_xor(dst, src1, src2, nbits) *dst = *src1 ^ *src2
+ * bitmap_andnot(dst, src1, src2, nbits) *dst = *src1 & ~(*src2)
+ * bitmap_complement(dst, src, nbits) *dst = ~(*src)
+ * bitmap_equal(src1, src2, nbits) Are *src1 and *src2 equal?
+ * bitmap_intersects(src1, src2, nbits) Do *src1 and *src2 overlap?
+ * bitmap_subset(src1, src2, nbits) Is *src1 a subset of *src2?
+ * bitmap_empty(src, nbits) Are all bits zero in *src?
+ * bitmap_full(src, nbits) Are all bits set in *src?
+ * bitmap_weight(src, nbits) Hamming Weight: number set bits
+ * bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n
+ * bitmap_shift_left(dst, src, n, nbits) *dst = *src << n
+ */
+
+/*
+ * Also the following operations in asm/bitops.h apply to bitmaps.
+ *
+ * set_bit(bit, addr) *addr |= bit
+ * clear_bit(bit, addr) *addr &= ~bit
+ * change_bit(bit, addr) *addr ^= bit
+ * test_bit(bit, addr) Is bit set in *addr?
+ * test_and_set_bit(bit, addr) Set bit and return old value
+ * test_and_clear_bit(bit, addr) Clear bit and return old value
+ * test_and_change_bit(bit, addr) Change bit and return old value
+ * find_first_zero_bit(addr, nbits) Position first zero bit in *addr
+ * find_first_bit(addr, nbits) Position first set bit in *addr
+ * find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit
+ * find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit
+ */
+
+/*
+ * The DECLARE_BITMAP(name,bits) macro, in xen/types.h, can be used
+ * to declare an array named 'name' of just enough unsigned longs to
+ * contain all bit positions from 0 to 'bits' - 1.
+ */
+
+/*
+ * lib/bitmap.c provides these functions:
+ */
+
+extern int __bitmap_empty(const unsigned long *bitmap, int bits);
+extern int __bitmap_full(const unsigned long *bitmap, int bits);
+extern int __bitmap_equal(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern void __bitmap_complement(unsigned long *dst, const unsigned long *src,
+ int bits);
+extern void __bitmap_shift_right(unsigned long *dst,
+ const unsigned long *src, int shift, int bits);
+extern void __bitmap_shift_left(unsigned long *dst,
+ const unsigned long *src, int shift, int bits);
+extern void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern int __bitmap_intersects(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern int __bitmap_subset(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+extern int __bitmap_weight(const unsigned long *bitmap, int bits);
+
+extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
+extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
+extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
+
+#define BITMAP_LAST_WORD_MASK(nbits) \
+( \
+ ((nbits) % BITS_PER_LONG) ? \
+ (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \
+)
+
+static inline void bitmap_zero(unsigned long *dst, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ *dst = 0UL;
+ else {
+ int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+ memset(dst, 0, len);
+ }
+}
+
+static inline void bitmap_fill(unsigned long *dst, int nbits)
+{
+ size_t nlongs = BITS_TO_LONGS(nbits);
+ if (nlongs > 1) {
+ int len = (nlongs - 1) * sizeof(unsigned long);
+ memset(dst, 0xff, len);
+ }
+ dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
+}
+
+static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
+ int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ *dst = *src;
+ else {
+ int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+ memcpy(dst, src, len);
+ }
+}
+
+static inline void bitmap_and(unsigned long *dst, const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ *dst = *src1 & *src2;
+ else
+ __bitmap_and(dst, src1, src2, nbits);
+}
+
+static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ *dst = *src1 | *src2;
+ else
+ __bitmap_or(dst, src1, src2, nbits);
+}
+
+static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ *dst = *src1 ^ *src2;
+ else
+ __bitmap_xor(dst, src1, src2, nbits);
+}
+
+static inline void bitmap_andnot(unsigned long *dst, const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ *dst = *src1 & ~(*src2);
+ else
+ __bitmap_andnot(dst, src1, src2, nbits);
+}
+
+static inline void bitmap_complement(unsigned long *dst, const unsigned long *src,
+ int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ *dst = ~(*src) & BITMAP_LAST_WORD_MASK(nbits);
+ else
+ __bitmap_complement(dst, src, nbits);
+}
+
+static inline int bitmap_equal(const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
+ else
+ return __bitmap_equal(src1, src2, nbits);
+}
+
+static inline int bitmap_intersects(const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
+ else
+ return __bitmap_intersects(src1, src2, nbits);
+}
+
+static inline int bitmap_subset(const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ return ! ((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits));
+ else
+ return __bitmap_subset(src1, src2, nbits);
+}
+
+static inline int bitmap_empty(const unsigned long *src, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
+ else
+ return __bitmap_empty(src, nbits);
+}
+
+static inline int bitmap_full(const unsigned long *src, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
+ else
+ return __bitmap_full(src, nbits);
+}
+
+static inline int bitmap_weight(const unsigned long *src, int nbits)
+{
+ return __bitmap_weight(src, nbits);
+}
+
+static inline void bitmap_shift_right(unsigned long *dst,
+ const unsigned long *src, int n, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ *dst = *src >> n;
+ else
+ __bitmap_shift_right(dst, src, n, nbits);
+}
+
+static inline void bitmap_shift_left(unsigned long *dst,
+ const unsigned long *src, int n, int nbits)
+{
+ if (nbits <= BITS_PER_LONG)
+ *dst = (*src << n) & BITMAP_LAST_WORD_MASK(nbits);
+ else
+ __bitmap_shift_left(dst, src, n, nbits);
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __XEN_BITMAP_H */
--- /dev/null
+#ifndef _LINUX_BITOPS_H
+#define _LINUX_BITOPS_H
+#include <asm/types.h>
+
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+
+static inline int generic_ffs(int x)
+{
+ int r = 1;
+
+ if (!x)
+ return 0;
+ if (!(x & 0xffff)) {
+ x >>= 16;
+ r += 16;
+ }
+ if (!(x & 0xff)) {
+ x >>= 8;
+ r += 8;
+ }
+ if (!(x & 0xf)) {
+ x >>= 4;
+ r += 4;
+ }
+ if (!(x & 3)) {
+ x >>= 2;
+ r += 2;
+ }
+ if (!(x & 1)) {
+ x >>= 1;
+ r += 1;
+ }
+ return r;
+}
+
+/*
+ * fls: find last bit set.
+ */
+
+static __inline__ int generic_fls(int x)
+{
+ int r = 32;
+
+ if (!x)
+ return 0;
+ if (!(x & 0xffff0000u)) {
+ x <<= 16;
+ r -= 16;
+ }
+ if (!(x & 0xff000000u)) {
+ x <<= 8;
+ r -= 8;
+ }
+ if (!(x & 0xf0000000u)) {
+ x <<= 4;
+ r -= 4;
+ }
+ if (!(x & 0xc0000000u)) {
+ x <<= 2;
+ r -= 2;
+ }
+ if (!(x & 0x80000000u)) {
+ x <<= 1;
+ r -= 1;
+ }
+ return r;
+}
+
+/*
+ * Include this here because some architectures need generic_ffs/fls in
+ * scope
+ */
+#include <asm/bitops.h>
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+static inline unsigned int generic_hweight32(unsigned int w)
+{
+ unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
+ res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+ res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
+ res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
+ return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
+}
+
+static inline unsigned int generic_hweight16(unsigned int w)
+{
+ unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
+ res = (res & 0x3333) + ((res >> 2) & 0x3333);
+ res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
+ return (res & 0x00FF) + ((res >> 8) & 0x00FF);
+}
+
+static inline unsigned int generic_hweight8(unsigned int w)
+{
+ unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
+ res = (res & 0x33) + ((res >> 2) & 0x33);
+ return (res & 0x0F) + ((res >> 4) & 0x0F);
+}
+
+static inline unsigned long generic_hweight64(__u64 w)
+{
+#if BITS_PER_LONG < 64
+ return generic_hweight32((unsigned int)(w >> 32)) +
+ generic_hweight32((unsigned int)w);
+#else
+ u64 res;
+ res = (w & 0x5555555555555555ul) + ((w >> 1) & 0x5555555555555555ul);
+ res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
+ res = (res & 0x0F0F0F0F0F0F0F0Ful) + ((res >> 4) & 0x0F0F0F0F0F0F0F0Ful);
+ res = (res & 0x00FF00FF00FF00FFul) + ((res >> 8) & 0x00FF00FF00FF00FFul);
+ res = (res & 0x0000FFFF0000FFFFul) + ((res >> 16) & 0x0000FFFF0000FFFFul);
+ return (res & 0x00000000FFFFFFFFul) + ((res >> 32) & 0x00000000FFFFFFFFul);
+#endif
+}
+
+static inline unsigned long hweight_long(unsigned long w)
+{
+ return sizeof(w) == 4 ? generic_hweight32(w) : generic_hweight64(w);
+}
+
+#endif
#define always_inline __inline__ __attribute__ ((always_inline))
-/* syslog levels ==> nothing! */
+/* Linux syslog levels. */
#define KERN_NOTICE ""
#define KERN_WARNING ""
#define KERN_DEBUG ""
#define KERN_EMERG ""
#define KERN_ALERT ""
+/* Linux 'checker' project. */
+#define __iomem
+#define __user
+
#ifdef VERBOSE
#define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \
__FILE__ , __LINE__ , ## _a )
--- /dev/null
+/*
+ * XXX This to be replaced with the Linux file in the near future.
+ */
+
+#ifndef __XEN_CPUMASK_H__
+#define __XEN_CPUMASK_H__
+
+#include <xen/bitmap.h>
+
+typedef u32 cpumask_t;
+
+extern cpumask_t cpu_online_map;
+
+static inline int cpus_weight(cpumask_t w)
+{
+ unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
+ res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+ res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
+ res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
+ return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
+}
+
+#define cpus_addr(_m) (&(_m))
+
+#endif /* __XEN_CPUMASK_H__ */
#define __XEN_IRQ_H__
#include <xen/config.h>
+#include <xen/cpumask.h>
#include <xen/spinlock.h>
#include <asm/regs.h>
#include <asm/hardirq.h>
void (*disable)(unsigned int irq);
void (*ack)(unsigned int irq);
void (*end)(unsigned int irq);
- void (*set_affinity)(unsigned int irq, unsigned long mask);
+ void (*set_affinity)(unsigned int irq, cpumask_t mask);
};
typedef struct hw_interrupt_type hw_irq_controller;
extern int smp_call_function(
void (*func) (void *info), void *info, int retry, int wait);
+/*
+ * Call a function on all processors
+ */
+static inline int on_each_cpu(void (*func) (void *info), void *info,
+ int retry, int wait)
+{
+ int ret = smp_call_function(func, info, retry, wait);
+ func(info);
+ return ret;
+}
+
/*
* True once the per process idle is forked
*/
#define cpu_logical_map(cpu) 0
#define cpu_number_map(cpu) 0
#define smp_call_function(func,info,retry,wait) 0
+#define on_each_cpu(func,info,retry,wait) ({ func(info); 0; })
#define cpu_online_map 1
#endif
+
+#ifdef __smp_processor_id
+#define smp_processor_id() __smp_processor_id()
+#else
+extern unsigned int smp_processor_id(void);
+#endif
+
#endif
#define write_lock(_lock) _raw_write_lock(_lock)
#define write_unlock(_lock) _raw_write_unlock(_lock)
+#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
+#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED
+
#endif /* __SPINLOCK_H__ */
#ifndef __TYPES_H__
#define __TYPES_H__
+#include <xen/config.h>
#include <asm/types.h>
+#define BITS_TO_LONGS(bits) \
+ (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
+#define DECLARE_BITMAP(name,bits) \
+ unsigned long name[BITS_TO_LONGS(bits)]
+
#ifndef NULL
#define NULL ((void*)0)
#endif